C# 对构造函数进行单元测试重要吗?
我应该对构造函数进行单元测试吗?假设我有一个这样的构造函数:C# 对构造函数进行单元测试重要吗?,c#,.net,unit-testing,constructor,C#,.net,Unit Testing,Constructor,我应该对构造函数进行单元测试吗?假设我有一个这样的构造函数: IMapinfoWrapper wrapper; public SystemInfo(IMapinfoWrapper mapinfoWrapper) { this.wrapper = mapinfoWrapper; } 我是否需要为此构造函数编写单元测试?我没有包装器变量的任何getter,因此不需要对其进行测试。否。它的功能将通过类上的其他每一个单元测试进行测试。是。如果构造函数中有逻辑,那么应该测试它。简单地设置属性不是
IMapinfoWrapper wrapper;
public SystemInfo(IMapinfoWrapper mapinfoWrapper)
{
this.wrapper = mapinfoWrapper;
}
我是否需要为此构造函数编写单元测试?我没有包装器变量的任何getter,因此不需要对其进行测试。否。它的功能将通过类上的其他每一个单元测试进行测试。是。如果构造函数中有逻辑,那么应该测试它。简单地设置属性不是逻辑。条件、控制流等是逻辑 编辑:
如果需要依赖项,您可能应该测试IMapinfoWrapper何时为null。如果是这样的话,那么这就是逻辑,您应该有一个测试来捕获您的ArgumentNullException或其他什么。。。测试是定义代码行为的规范。如果它抛出ArgumentNullException,那么应该在测试中指定它。单元测试是关于测试对象的公共状态、行为和交互 如果您只是在构造函数中设置一个私有字段,那么需要测试什么
不要费心对简单的访问器和变异器进行单元测试。这太傻了,对任何人都没有帮助。我相信100%的覆盖率。此外,100%的覆盖率不是通过简单的模拟测试简单的交互,或者只是设置和获取东西,而是更多的检查功能的集成/验收测试。因此,如果您最终编写了非常好的集成/验收测试,那么应该调用所有构造函数(以及setter和getter等简单方法)。SystemInfo的实例的行为取决于
包装器的值
如果出现任何错误(例如,null值导致中断),那么我建议编写描述每种情况的场景,并使用它们来驱动适当单元测试的定义
如果所有场景最终都依赖于IMapinfoWrapper
私有实例的状态或行为,那么我建议改为在该类上编写单元测试。单元测试是关于检查执行路径的,通常被称为
如果没有路径可供选择,则没有If、no loop、no GOTO(=p)这不是很有用Q:如果要在构造函数中设置成员变量,为什么要设置它
答:因为您有一个失败的单元测试,只有在构造函数中设置它才能使其通过
如果您使用这种逻辑,即您只编写代码以使单元测试通过(测试驱动开发),那么您就已经有了问题的答案。除非您正在编写编译器,否则您将不会这样做,因为您将只测试编译器是否可以生成代码来执行分配,这通常是毫无意义的
现在,在一个更常见的情况下,如果你想用包装器做些别的事情,那么也许有一点。例如,如果试图传递null,则可以抛出ArgumentNullException,理论上,这可能需要进行单元测试。即使这样,测试的价值也非常小
就个人而言,我几乎从不显式地测试构造函数。如果它们足够复杂,需要测试,我倾向于觉得代码有点难闻。如果构造函数包含一些逻辑,比如初始化一个类,我认为您应该测试这个构造函数。或者你可以告诉开发人员,将初始化放在构造函数中会降低被测代码的可测试性。在许多受FDA监管的环境中,更关键的代码必须经过100%测试…包括类的构造。因此,无论是否测试构造函数,对构造函数的测试有时都是必要的。此外,使用静态分析工具的公司需要确保一个类的所有数据成员都已正确初始化,以避免出现错误,尽管代码可能运行平稳且没有错误。通常,数据成员初始化是在构造函数中完成的……值得思考。测试访问器和变异器也是必要的,除非开发人员确保不能更改任何状态逻辑。例如,如果对单例使用设计模式,通常会使用访问器或属性,如果类未初始化,则会从访问器完成,因为构造函数是私有的。在C++中,可以使函数保持不变或静态,类中的数据成员不能更改。(注意:即使使用静态变量也有点风险,因为这些变量通常是全局变量。)然而,如果没有测试,如果有人没有使用预防措施,您如何保证100%的准确性,即所写内容不会随着时间的推移而变成故障?维护很难做到万无一失。这要看情况而定
我不会为像您给出的示例这样简单的东西编写专门的构造函数测试
但是,如果在构造函数中有逻辑测试,例如参数验证,那么绝对是。虽然,像最初的海报一样,如果可能的话,我在构造函数中不做任何工作,但通常必须进行参数验证。在这种情况下,不可避免地要阻止建造师做一些工作。如果构造函数中有逻辑,那么它总是有可能出错,因此我将其视为任何其他方法调用,并对其进行适当的测试。您绝对应该测试构造函数。如果你有一个默认的构造函数,你应该测试它是否可以被调用。如果以后该类被更改了——可能它变成了一个单例,或者默认构造函数被删除,取而代之的是一个需要参数的构造函数,该怎么办?在这种情况下,测试应该失败,以警告该更改(以便可以修复类或测试以满足新需求)
默认构造函数的存在是一个需要进行测试的需求。即使构造函数所做的一切都是设置将在其他地方测试的私有成员,也应该测试存在无参数构造函数的事实。我认为
[TestMethod]
public void Constructor_FullTest()
{
IDrawingContext context = new Mock<IDrawingContext>().Object;
ConstructorTests<Frame>
.For(typeof(int), typeof(int), typeof(IDrawingContext))
.Fail(new object[] { -3, 5, context }, typeof(ArgumentException), "Negative length")
.Fail(new object[] { 0, 5, context }, typeof(ArgumentException), "Zero length")
.Fail(new object[] { 5, -3, context }, typeof(ArgumentException), "Negative width")
.Fail(new object[] { 5, 0, context }, typeof(ArgumentException), "Zero width")
.Fail(new object[] { 5, 5, null }, typeof(ArgumentNullException), "Null drawing context")
.Succeed(new object[] { 1, 1, context }, "Small positive length and width")
.Succeed(new object[] { 3, 4, context }, "Larger positive length and width")
.Assert();
}