90

我应该对构造函数进行单元测试吗?假设我有一个这样的构造函数:

IMapinfoWrapper wrapper;
public SystemInfo(IMapinfoWrapper mapinfoWrapper)
{
    this.wrapper = mapinfoWrapper;
}

我需要为此构造函数编写单元测试吗?我没有任何包装变量的吸气剂,所以我不需要测试它。

4

15 回答 15

107

单元测试是关于测试对象的公共状态、行为和交互。

如果您只是在构造函数中设置一个私有字段,那么有什么要测试的?

不要费心对简单的访问器和修改器进行单元测试。这很愚蠢,对任何人都没有帮助。

于 2008-12-10T23:14:56.940 回答
51

是的。如果您的构造函数中有逻辑,则应该对其进行测试。简单地设置属性不是逻辑 IMO。条件、控制流等 IS 逻辑。

编辑: 如果需要该依赖项,您可能应该测试 IMapinfoWrapper 何时为空。如果是这样,那么这就是逻辑,你应该有一个测试来捕获你的 ArgumentNullException 或其他什么......你的测试是定义代码行为方式的规范。如果它抛出 ArgumentNullException,那么应该在测试中指定。

于 2008-12-10T23:10:25.483 回答
15

问:如果你在构造函数中设置一个成员变量,你为什么要设置它。

答:因为您有一个失败的单元测试,只能通过在构造函数中设置它才能通过。

如果您使用这种逻辑,您只编写代码以使单元测试通过(测试驱动开发),那么您已经有了问题的答案。

于 2008-12-11T21:02:03.383 回答
10

不会。它的功能将由该类的所有其他单元测试进行测试。

于 2008-12-10T23:09:37.263 回答
7

你绝对应该测试构造函数。如果你有一个默认构造函数,你应该测试它是否可以被调用。如果以后类被改变了——也许它变成了一个单例或者默认构造函数被删除以支持一个需要参数的类怎么办?在这种情况下,测试应该失败以提醒该更改(以便可以修复类或测试以满足新要求)。

默认构造函数的存在是应该进行测试的要求。即使构造函数所做的只是设置将在别处测试的私有成员,也应该测试存在无参数构造函数的事实。

于 2012-02-09T16:16:19.367 回答
5

这取决于。

我不会为您给出的示例如此简单的事情编写专用的构造函数测试。

但是,如果您在构造函数中进行了逻辑测试,例如参数验证,那么绝对可以。尽管像原始海报一样,如果可能的话,我不会在构造函数中进行任何工作,但通常必须进行参数验证。在这种情况下,不可避免地要阻止构造函数做一些工作。如果构造函数中存在逻辑,则总是有可能出错,因此我将其视为任何其他方法调用并适当地对其进行测试。

于 2010-02-20T19:53:52.360 回答
5

我正在测试包含逻辑的构造函数——例如验证或有条件地设置私有状态。验证错误最终会导致构造函数抛出异常。成功的执行最终会创建一个对象,该对象根据构造函数中设置的状态表现出特定的行为。无论哪种方式,它都需要测试。但是构造函数测试很无聊,因为它们看起来都一样——调用构造函数,做出断言。测试方法声明通常比整个测试逻辑占用更多的空间......所以我写了一个简单的测试库来帮助为构造函数编写声明性测试:如何在 C# 构造函数中轻松测试验证逻辑

这是一个示例,其中我在一个类的构造函数上尝试了七个测试用例:

[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();

}

通过这种方式,我可以为我的构造函数测试所有相关案例,而无需输入太多内容。

于 2014-06-16T10:33:39.300 回答
3

在许多受 FDA 监管的环境中,必须对更关键的代码进行 100% 测试……包括类的构建。因此,有时需要对构造函数进行测试,而不管是否要测试它们。此外,使用静态分析工具的公司将需要确保一个类的所有数据成员都正确初始化,以便没有错误,尽管代码可以顺利运行并且没有错误。通常数据成员初始化是在构造函数中完成的……只是值得深思。

于 2010-02-20T19:45:46.710 回答
2

我认为这个问题的答案是“是”。

那里有很多代码可怕地假设一个初始化的对象状态,而不是一个空引用——通常是在构造函数中没有明确分配值的时候。

当初始化的公共成员值发生更改时,我很高兴让构造函数测试中断以提醒我。这是关于防御性测试的——我很务实,并且比没有测试更快乐,当它们被证明无用或无用时将其删除。

于 2013-10-15T01:55:59.727 回答
1

我相信100%的覆盖率。此外,100% 的覆盖率不是通过简单地通过模拟事物或设置和获取事物来测试简单的交互,而是通过更多的集成/验收测试来检查功能。因此,如果您最终编写了非常好的集成/验收测试,则应该调用您的所有构造函数(以及简单的方法,例如 setter 和 getter)。

于 2008-12-10T23:22:40.980 回答
1

除非开发人员确保不能更改任何状态逻辑,否则测试访问器和修改器也是必要的。例如,如果使用 Singleton 的设计模式,则通常会使用访问器或属性,并且如果未初始化类,则从访问器完成,因为构造函数是私有的。在 C++ 中,可以将它们的函数设为 const 或 static,其中类的数据成员不能更改。(注意:即使使用 static 也有一点风险,因为这些变量通常是全局的。)但是,如果没有测试,如果有人没有使用预防措施,你怎么能保证 100% 准确,写的东西不会成为失败时间?维护并非万无一失。

于 2010-02-20T19:50:05.517 回答
0

的实例的什么行为SystemInfo取决于 的值wrapper

如果有任何问题(例如空值导致损坏),那么我建议编写描述每种情况的场景并使用它们来驱动适当单元测试的定义。

如果所有场景最终都依赖于 的私有实例的状态或行为IMapinfoWrapper,那么我建议改为在该类上编写单元测试。

于 2008-12-10T23:31:31.757 回答
0

除非您正在编写编译器,否则不会,因为您只会测试编译器是否可以生成代码来执行分配,这通常是没有意义的。

现在,在更常见的情况下,如果您想用包装器做其他事情,那么也许有一点。例如,如果您尝试传递空值,则可以抛出 ArgumentNullException,理论上,这可以进行单元测试。即使这样,测试的价值也很小。

就个人而言,我几乎从不明确测试构造函数。如果它们足够复杂以至于需要测试,我倾向于觉得代码有点臭。

于 2008-12-12T12:48:52.747 回答
0

如果构造函数包含一些逻辑,比如初始化一个类,我认为你应该测试这个构造函数。或者您可以与开发人员交谈,将初始化放在构造函数中会降低被测代码的可测试性。

于 2008-12-19T10:03:45.910 回答
-1

单元测试是关于检查执行路径,通常称为循环复杂性

如果你没有可供选择的路径,没有 if,没有循环,没有 GOTO (=P) 它不是很有用

于 2008-12-10T23:37:49.700 回答