使用 Mockito 对 Runnable 进行单元测试
Unit test for Runnable with Mockito
我有这样的代码,我想为其编写单元测试。
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();
}
});
}
}
如何使用 Mockito / Powermockito 验证是否调用了 callHandler() 方法。
将模拟 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();
绕过并发
如果您只是想确定是否调用了处理程序,则可以使用在同一线程上执行的 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();
另一种处理并发问题的方法是模拟 Executor 在被调用时“什么也不做”,并在测试中使用 ArgumentCaptor
来捕获它会调用的 Runnable。拥有 Runnable 后,您可以在与测试相同的线程中手动调用它。
这是一个例子:
@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();
}
我有这样的代码,我想为其编写单元测试。
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();
}
});
}
}
如何使用 Mockito / Powermockito 验证是否调用了 callHandler() 方法。
将模拟 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();
绕过并发
如果您只是想确定是否调用了处理程序,则可以使用在同一线程上执行的 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();
另一种处理并发问题的方法是模拟 Executor 在被调用时“什么也不做”,并在测试中使用 ArgumentCaptor
来捕获它会调用的 Runnable。拥有 Runnable 后,您可以在与测试相同的线程中手动调用它。
这是一个例子:
@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();
}