代码之家  ›  专栏  ›  技术社区  ›  Nathan W

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

  •  67
  • Nathan W  · 技术社区  · 16 年前

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

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

    我需要为这个构造函数编写一个单元测试吗?包装变量没有任何getter,因此不需要测试它。

    15 回复  |  直到 7 年前
        1
  •  87
  •   yfeldblum    16 年前

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

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

    不要麻烦单元测试简单的访问器和转换器。这太傻了,对任何人都没有帮助。

        2
  •  31
  •   Brian Genisio    13 年前

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

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

        3
  •  13
  •   John Sonmez    16 年前

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

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

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

        4
  •  7
  •   Draemon    16 年前

    不,它的功能将通过类上的其他单元测试来测试。

        5
  •  6
  •   c g    13 年前

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

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

        6
  •  3
  •   Brandon    15 年前

    在许多FDA规定的环境中,更关键的代码必须100%测试……包括类的构造。因此,对构造器的测试有时是必要的,不管是否有理由去测试它们。此外,使用静态分析工具的公司将需要确保类的所有数据成员都正确初始化,以避免出现错误,尽管代码可能运行顺利且没有错误。通常,数据成员初始化是在构造函数中完成的……只是供思考的食物。

        7
  •  3
  •   Zoran Horvat    7 年前

    我正在测试包含逻辑的构造函数,例如验证或条件设置私有状态。验证错误以从构造函数引发的异常结束。成功执行的结果是创建一个对象,该对象根据构造函数中设置的状态显示特定的行为。 不管怎样,它都需要测试。但是构造函数测试很无聊,因为它们看起来都一样-调用构造函数,做出断言。测试方法声明通常比整个测试逻辑占用更多的空间…因此,我编写了一个简单的测试库,它帮助编写构造函数的声明性测试: How to Easily Test Validation Logic in Constructors in 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();
    
    }
    

    这样,我就可以为构造函数测试所有相关的案例,而无需键入太多内容。

        8
  •  2
  •   Mark Simpson    15 年前

    这要看情况而定。

    我不想为像您给出的示例这样简单的东西编写专门的构造函数测试。

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

        9
  •  1
  •   digiarnie    16 年前

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

        10
  •  1
  •   Brandon    15 年前

    测试访问器和转换器也是必要的,除非开发人员已经确保状态逻辑不能被更改。例如,如果将设计模式用于单实例,则通常会使用访问器或属性,并且如果类未初始化,则会从访问器执行,因为构造函数是私有的。在C++中,可以使它们的函数保持不变或静态,其中类的数据成员不能更改。(注意:即使使用静态变量也有一定的风险,因为这些变量通常是全局变量。)但是,如果没有测试,如果有人未能使用预防措施,您如何以100%的准确率保证所写内容不会随着时间而变为失败?维护很难做到万无一失。

        11
  •  1
  •   badcop666    12 年前

    我认为答案是“是的”。

    外面有很多代码,它们可怕地假设一个初始化的对象状态,而不是一个空引用——通常是在构造函数中没有指定显式值的情况下。

    我很高兴让构造函数测试中断,以便在初始化的公共成员值发生更改时提醒我。这是关于防御测试的——我是务实的,比起没有测试我更乐于接受测试,当测试被证明没有帮助或有用时,我会删除它们。

        12
  •  0
  •   joel.neely    16 年前

    一个实例的什么行为 SystemInfo 取决于 wrapper ?

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

    如果所有场景最终都依赖于 IMapinfoWrapper ,那么我建议在那个类上编写单元测试。

        13
  •  0
  •   Jim Cooper    16 年前

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

    现在,在更常见的情况下,如果您想用包装器做其他事情,那么可能有一点。例如,如果您试图传递一个空值,那么可以抛出一个argumentNullException,从理论上讲,它可以有一个单元测试。即使这样,测试的值也是非常小的。

    就个人而言,我几乎从未显式地测试构造函数。如果它们足够复杂,需要测试,我会觉得代码有点难闻。

        14
  •  0
  •   Magus    16 年前

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

        15
  •  -1
  •   Eric    16 年前

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

    如果你没有可供选择的路径,没有if,没有loop,没有goto(=p),这不是很有用的。