使用Mockito进行Runnable的单元测试

Ank*_*kit 3 java unit-testing mocking mockito powermockito

我有一个这样的代码,我想为其编写单元测试。

public class TestClass {

private final Executor executor;
private final Handler handler;

TestClass(Executor executor, Handler handler) {
    this.executor = executor;
    this.handler = handler;
}

void doSomething(String param1) {
    executor.execute(new Runnable() {
        @Override
        public void run() {
            //do something
            handler.callHandler();
        }
    });
}
}
Run Code Online (Sandbox Code Playgroud)

我如何使用Mockito / Powermockito来验证是否调用了callHandler()方法。

bow*_*ore 5

将模拟传递Handler给的构造函数TestClass

然后使用Mockito.verify()断言该callHandler()方法已被调用。

涉及并发

您可以对倒计时的答案进行存根CountDownLatch以使测试等待处理程序被击中。等待将涉及设置合理的超时时间,这可能很棘手,您不希望它太高,否则失败会使测试运行更长的时间,而又不会太低,因此您不会得到误报。

Handler handler = mock(Handler.class);
CountDownLatch finished = new CountDownLatch(1);

doAnswer(invocation -> {
    finished.countDown();
    return null;
}).when(handler).callHandler();

TestClass testClass = new TestClass(executor, handler);

testClass.doSomething("thisThing");

boolean ended = finished.await(10, TimeUnit.SECONDS);

assertThat(ended).isTrue();

verify(handler).callHandler();
Run Code Online (Sandbox Code Playgroud)

绕过并发

如果仅尝试确定是否调用了处理程序,则可以使用Executor在同一线程上执行的。这将使测试更加稳定。

Handler handler = mock(Handler.class);
Executor executor = new Executor() {
    @Override
    public void execute(Runnable command) {
        command.run();
    }
};

TestClass testClass = new TestClass(executor, handler);

testClass.doSomething("thisThing");

verify(handler).callHandler();
Run Code Online (Sandbox Code Playgroud)