[英]Unit test for Runnable with Mockito
I have a code like this for which I would like to write unit test.我有一个这样的代码,我想为其编写单元测试。
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();
}
});
}
}
How can I use Mockito / Powermockito to verify if the callHandler() method is invoked.如何使用 Mockito / Powermockito 来验证 callHandler() 方法是否被调用。
Pass a mock Handler
to the constructor of TestClass
. 将模拟
Handler
传递给TestClass
的构造函数。
Then use Mockito.verify()
to assert that callHandler()
method was called. 然后使用
Mockito.verify()
断言调用了callHandler()
方法。
You can stub an answer that counts down on a CountDownLatch
to make the test wait for the handler to be hit. 您可以存储一个在
CountDownLatch
上倒计时的答案,以使测试等待处理程序被命中。 Waiting will involve setting a reasonable timeout, which can be tricky, you don't want it too high, or failure will make the test run much longer, and not too low so that you don't get false positives. 等待将涉及设置合理的超时,这可能会非常棘手,你不希望它太高,或失败会使试运行更长的时间,而不是太低了,这样你就不会得到误报。
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();
If you're only trying to determine whether the handler is invoked you can use an Executor
that executes on the same thread. 如果您只是尝试确定是否调用了处理程序,则可以使用在同一线程上执行的
Executor
。 This will make for a more stable test. 这将使测试更加稳定。
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();
Another way you can handle the concurrency issue is to mock the Executor to "do nothing" when called and use an ArgumentCaptor
in your test to capture the Runnable it would have invoked.处理并发问题的另一种方法是模拟 Executor 在调用时“什么都不做”,并在测试中使用
ArgumentCaptor
来捕获它会调用的 Runnable。 Once you have the Runnable you can manually invoke it in the same thread as your test.拥有 Runnable 后,您可以在与测试相同的线程中手动调用它。
Here's an example:下面是一个例子:
@Mock
private Executor executor;
@Mock
private Handler handler;
@Before
public void setup() {
openMocks(this);
doNothing().when(executor).execute(any());
}
@Test
public void runTest() {
TestClass testClass = new TestClass(executor, handler);
testClass.doSomething("the thing");
ArgumentCaptor<Runnable> runnable = ArgumentCaptor.forClass(Runnable.class);
verify(executor).execute(runnable.capture());
Runnable capturedRunnable = runnable.getValue();
capturedRunnable.run();
verify(handler).callHandler();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.