繁体   English   中英

单元测试构造函数是否重要?

[英]Is it important to unit test a constructor?

我应该对单元测试构造函数吗? 说我有这样的构造函数:

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

我是否需要为这位建筑师编写单元测试? 我没有包装器变量的任何getter,所以我不需要测试它。

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

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

不要打扰单元测试你的简单访问器和mutator。 那太傻了,对任何人都没有帮助。

是。 如果构造函数中有逻辑,则应测试它。 简单地设置属性不是逻辑IMO。 条件,控制流等IS逻辑。

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

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

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

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

不会。它的功能将通过课堂上的每个其他单元测试进行测试。

你绝对应该测试构造函数。 如果您有默认构造函数,则应测试是否可以调用它。 如果稍后更改类会怎么样 - 也许它会变成单例或删除默认构造函数而不是需要参数? 在这种情况下,测试应该失败以警告该更改(以便可以修复类或测试以满足新要求)。

默认构造函数的存在是应该进行测试的要求。 即使所有构造函数都设置了将在其他地方测试的私有成员,也应测试存在无参数构造函数的事实。

我在构造函数包含逻辑时进行测试 - 例如验证或条件设置私有状态。 验证错误最终在构造函数抛出的异常中结束。 成功执行最终会创建一个对象,该对象根据构造函数中设置的状态显示特定的行为。 无论哪种方式,都需要测试。 但构造函数测试很无聊,因为它们看起来都一样 - 调用构造函数,进行断言。 测试方法声明通常占用比整个测试逻辑更多的空间......所以我写了一个简单的测试库,它有助于为构造函数编写声明性测试: 如何在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();

}

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

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

这取决于。

我不打算为你给出的例子这么简单的东西写一个专门的构造函数测试。

但是,如果您在构造函数中进行了逻辑测试,例如参数验证,那么绝对是。 虽然像原始海报一样,如果可能,我在构造函数中不起作用,但通常必须进行参数验证。 在这种情况下,不可避免地使构造函数不做某些工作。 如果构造函数中存在逻辑,那么它总是存在错误的可能性,因此我将其视为任何其他方法调用并对其进行适当测试。

我认为答案是肯定的。

有很多代码可以假设一个初始化的对象状态,而不是空引用 - 通常在构造函数中没有指定显式值时。

我很高兴在初始化的公共成员值被更改时,构造函数测试会中断以提醒我。 这是关于防御性测试 - 我是务实的,并且更乐于接受测试,并且当它们被证明没有帮助或有用时将它们移除。

除非开发人员确保不能更改状态逻辑,否则还必须测试访问器和更改器。 例如,如果使用Singleton的设计模式,通常会使用访问器或属性,如果未初始化类,则由访问器完成,因为构造函数是私有的。 在C ++中,可以使其函数为const或static,其中类的数据成员不能更改。 (注意:即使使用静态也有点风险,因为这些变量通常是全局的。)但是,如果没有测试,如果有人未能使用预防措施,您如何能够100%准确地保证所写的内容不会成为故障时间? 维护很难万无一失。

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

SystemInfo实例的行为取决于wrapper的值?

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

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

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

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

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

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

单元测试是关于检查执行路径,通常称为Cyclomatic Complexity

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM