如何对回调逻辑进行单元测试?

时间:2011-08-22 13:16:56

标签: java unit-testing callback

更完整的问题是,给定一个期望回调作为参数的依赖项,如何编写覆盖回调逻辑的单元测试仍设法模拟依赖项?

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会导致回调逻辑未被测试。此外,回调逻辑似乎应该是私有的,所以我不希望直接测试它;也许这是我的误解。

由于回调被相当广泛地使用,我希望有一种常用的方法来测试它们,但我还没有找到它。

5 个答案:

答案 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怎么样?

然后你只需要感知效果 - 如果你的回调被执行就应该观察到的变化。