更完整的问题是,给定一个期望回调作为参数的依赖项,如何编写覆盖回调逻辑的单元测试和仍设法模拟依赖项?
public class DoStuff {
public void runThis(Runnable callback) {
// call callback
}
}
public class ClassUnderTest {
private DoStuff stuffToDo;
public void methodUnderTest() {
this.stuffToDo.runThis(/*a runnable with some logic*/)
}
}
在上面的例子中,我会模拟stuffToDo
,因为我应该验证方法调用的调用和模拟输出。但是,模拟runThis
会导致回调逻辑未被测试。此外,回调逻辑似乎应该是私有的,所以我不希望直接测试它;也许这是我的误解。
由于回调被相当广泛地使用,我希望有一种常用的方法来测试它们,但我还没有找到它。
答案 0 :(得分:10)
你不能在一次测试中。如果你嘲笑某事,它的模拟,这意味着它只能验证参数并模拟返回值(你在测试中配置)。
事实上,模仿某事的全部意义在于测试单独使用模拟的内容。如果你想要DoStuff
的单元测试,你不必担心使用一些可能或可能不起作用的回调实现。你嘲笑回调,所以你不必担心它。
您仍然可以通过单独测试回调代码,和单独测试回调用户(使用模拟回调)并且可能通过抛出集成测试来进行良好测量,您将完全配置的组件作为一个整体使用。
答案 1 :(得分:1)
这里基本上你想测试类 DoStuff 。这意味着您需要对DoStuff中的所有方法进行彻底测试,对吧?所以在这种情况下,你需要做的是,而不是嘲笑 stuffToDo 本身,注入一个模拟的Runnable到stuffToDo。然后检查您的runnable是否成功执行。
但是如果你在课堂上有其他功能,你可以进行单独测试并模拟它们。
答案 2 :(得分:0)
在你的特定情况下,听起来你已经测试过DoStuff
(或者因为它被嘲笑而不再关心)现在特别是对你所特定的Runnable
进行单元测试设计的。在这种情况下,callback
听起来就像您想要测试的那样,就像有人可能希望直接对数据库策略或内存策略进行单元测试一样。
如果您正在尝试这样做,或者您可以在黑匣子中进行测试,并尽可能通过ClassUnderTest
进行测试。或者,您可以在特定的Runnable上创建测试工具。如果您要发布此代码并且不希望使测试工具可访问,则可以将测试工具方法设为私有,并专门与单元测试程序集共享其详细信息。
查看here以获取有关如何制作朋友程序集的信息。我通常签署我的单元测试代码,这样我就不必使用命令行编译器了。我想这取决于你的构建环境。
答案 3 :(得分:0)
如果您使用EasyMock,则可以使用andStubAnswer
来调用runnable。
doSomethingMock.runThis(runnable);
expectLastCall().andStubAnswer(new IAnserable<Void>() {
Runnable runnable = (Runnable)getCurrentArguments()[0];
runnable.run();
return null;
});
我想其他模拟框架包含类似的内容。
答案 4 :(得分:0)
只是无条件地调用Runnable的假DoStuff怎么样?
然后你只需要感知效果 - 如果你的回调被执行就应该观察到的变化。