我有很多类类似于下面的类:
public class Foo
{
private readonly Ba _ba;
private Foo(Ba ba)
{
if (ba is null) throw new ArgumentNullException(ba);
_ba = ba;
}
}
在其他类的内部,我将这个构造函数称为 Foo
,但由于这是无意的,因此在每个构造函数调用中 ba
都不是 null
.
我为组成框架写了很多测试方法,但我无法达到 100% 的代码覆盖率,因为上面代码片段中的异常是较新抛出的。
我看到以下替代方案:
- 删除 null 检查:这适用于当前的项目实现,但每当我可能添加意外调用
Foo(null)
时,调试都会更加困难。 - 用
[ExcludeFromCodeCoverage]
修饰构造函数: 这适用于当前的Foo(Ba)
实现,但每当我可能更改实现时,构造函数中的新代码路径可能会开发并意外地错过测试。
你会如何解决这个难题?
注意事项
代码示例是用 C# 编写的,但问题可能涉及一般单元测试/异常处理问题。
C# 8 可能会通过 introducing non-nullable reference types 解决这个问题,但我正在寻找一个好的解决方案,直到它稳定发布。
最佳答案
您错过了最重要的替代方案:不要将其视为实现 100% 代码覆盖率的理想目标。
严格来说,代码中的稳健性检查无法以合理的方式进行测试。这也会发生在代码的其他各个部分 - 它经常发生在 switch 语句中,其中明确涵盖所有可能的情况,并且添加额外的默认情况只是为了抛出异常或以其他方式处理这种“不可能”的情况。或者,考虑添加到代码中的断言语句:由于断言永远不会失败,严格来说,您将永远无法覆盖隐藏在断言语句中的 else
分支——您如何测试断言中的表达式是否有助于实际检测到您想要它检测到的问题?
删除此类健壮性代码和断言不是一个好主意,因为它们还可以保护您免受 future 更改的不良副作用。对于您展示的示例,从覆盖率分析中排除代码可能是可以接受的,但在我提到的大多数情况下,这不是一个好的选择。最后,您必须做出明智的决定(通过详细查看覆盖率报告,而不仅仅是整体百分比)代码的哪些语句/分支等确实需要覆盖,哪些不需要。
最后一点,请注意,高代码覆盖率并不一定表示您的测试套件质量高。如果您的测试套件能够检测到代码中可能存在的错误,那么它就是高质量的。您可以拥有一个 100% 覆盖率的测试套件,它不会检测到任何潜在的错误。
关于c# - 内部安全检查,如何做到100%的代码覆盖率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55562538/