在测试过程中使用特殊构造函数是代码味道吗?

时间:2011-06-05 18:27:42

标签: java unit-testing testing constructor

假设我有一个类Foo,它只使用类Bar的实例进行实例化:

public Foo(Bar x) {
    this.a = x.a();
    this.b = x.b();
    ...
}

现在我想测试Foo,进一步假设难以创建具有所需状态的Bar实例。作为附加约束,字段a, b, ...被声明为final,因此这些字段的setter不可用。

可能是在Foo中创建一个额外的构造函数:

protected Foo(A a, B b, ...) {
    this.a = a;
    this.b = a;
    ...
}

此构造函数仅在测试期间使用,我将在此构造函数的注释中声明。

问题:这是代码味吗?

我想到的另一个解决方案是嘲笑Bar。想知道它是否是这种情况下的最佳做法?

3 个答案:

答案 0 :(得分:9)

模拟栏更有可能被视为最佳实践。你应该可以创建一个MockBar,这样就可以了

Foo foo = new Foo(new MockBar(a, b));

答案 1 :(得分:4)

我可能会认为这种形式很差,但如果它有效,它就有效。一个更好的解决方案是创建一个TestBar类,它是Bar的子类,并覆盖Bar中的方法。正如你在问题中提到的那样,我猜这几乎是在嘲笑这个对象。它更清晰,允许您定义测试驱动程序可以包含的不同Bar实现。

答案 2 :(得分:0)

Hmmmmmm。

  • 如果问题是难以创建/繁琐的条形,则可以轻松地创建它们。
  • 您为什么也没有一个构造函数,该构造函数具有从Bar对象获取的任意数量的参数?好像是包装纸或刀之类的东西。 可以通过使用包装程序避免20或30 arg的调用,但是调用者将如何创建包装程序(不使用20或30 arg的情况)创建包装器或使用20层或30层“返回此”设置程序的链调用)?

也就是说,您说的是什么 种类 ?如果要测试的东西是单独的方法,或者要测试的东西是我们可以得到的最类似于生产的环境中的整个应用程序,那么在创建环境所需的条件上有很大的不同对于要测试的东西。 “如我们所愿,就像生产一样”意味着您 不应执行任何旨在使测试成功的代码。在针对应用程序较小部分的测试中,这几乎没有什么问题。 “测试”并不总是与“测试”相同。测试汽车防滚架意味着像测试一样可以承受是否能够承受锡所承受的扭矩。在测试整辆车时,您不会做同样的事情。测试零件与测试整个装配体是不同的。