仅在测试期间使用特殊的构造函数是否有代码味道?
假设我有一个类 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。想知道在这种情况下这是否是最佳实践?
Assume I have a class Foo
which is only instantiated with an instance of class Bar
:
public Foo(Bar x) {
this.a = x.a();
this.b = x.b();
...
}
Now I would like to test Foo
, further assuming an instance of Bar
with the desired state is difficult to create. As an additional constraint, the fields a, b, ...
are declared as final, so setters for this fields are not available.
A possibility would be to create an additional constructor in Foo:
protected Foo(A a, B b, ...) {
this.a = a;
this.b = a;
...
}
This constructor is only used during testing, which I would declare in the comment for this constructor.
Question: Is this a code smell?
Another solution I was thinking of was mocking Bar
. Wonder if its the best practice in this case?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Mocking Bar 更有可能被认为是最佳实践。您应该能够创建一个 MockBar,这样您就可以执行以下操作
Mocking Bar is more likely to be considered best practice. You should be able to create a MockBar so you can do
我可能会认为这种形式很糟糕,但如果它有效,它就有效。更好的解决方案是创建一个
TestBar
类,它是Bar
的子类,并覆盖Bar
中的方法。我想这几乎是在嘲笑该对象,正如您在问题中提到的那样。它更加简洁,并允许您定义可以包含在测试驱动程序中的不同的Bar
实现。I would probably consider that poor form, but if it works, it works. A preferable solution would be making a
TestBar
class that is a sub-class ofBar
and overrides the methods inBar
. I guess that's pretty much mocking the object, as you alluded to in your question. It's a lot cleaner and allows you to define a differentBar
implementation that can be included by your test driver.嗯嗯嗯。
也就是说,您所说的测试是什么类型?如果要测试的东西是单独的方法,或者要测试的东西是我们可以获得的最接近生产环境的整个应用程序,那么创建环境所需的内容就会产生严重的差异对于要测试的东西。 “尽可能像生产一样”具体意味着您不应该执行任何旨在使测试成功的代码。在针对应用程序的较小单个部分的测试中,这稍微不是什么问题。 “测试”并不总是与“测试”相同。测试汽车的防滚架意味着测试它是否能够承受其声称可以承受的扭矩。测试整辆车时,您不会做同样的事情。测试零件与测试整个组件不同。
Hmmmmmm.
That said, what kind of tests are you speaking of ? If the thing-to-be-tested is individual methods or the thing-to-be-tested is the entire application in the most production-like setting we can get, that makes a serious difference as to what it takes to create the environment for the thing-to-be-tested. "As production-like as we can get" means specifically you should not be executing any code whose purpose is just to make the test succeed. That is somewhat less of a problem in tests targeted at smaller individual parts of the application. "Testing" is not always the same thing as "testing". Testing rollbars for cars means stuf like testing whether it can take the torque it says it can take on the tin. You don't do the same stuff when testing the entire car. Testing a part is not the same thing as testing the entire assembly.