问题是我有一个方法来启动一个新线程来完成一项耗时的工作。我想测试回调结果,但子线程可能仍在运行,因此,我得到的不是正确的 stub 。
我认为代码可以解释自己:
public class JustAClass {
//it is a callback for async
public interface JustACallBack {
void callFunc(JustAResult result);
}
//this is the result interface
public interface JustAResult {
}
//this is a real class for the interface
public class JustAResultReal implements JustAResult{
public JustAResultReal(String content) {this.content = content;}
public String content;
}
//here is the key function
public void threadFunc(final JustACallBack callBack) {
BCCache.executorService.execute(new Runnable() {
@Override
public void run() {
//just to simulate a time-consuming task
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//now we callback
callBack.callFunc(new JustAResultReal("can you reach me"));
}
});
}
}
测试函数可以是(我正在使用mockito
):
@Test
public void testThreadFunc() throws Exception {
JustAClass justAClass = new JustAClass();
JustAClass.JustACallBack callBack = Mockito.mock(JustAClass.JustACallBack.class);
justAClass.threadFunc(callBack);
//add this line, we can get the expected result
Thread.sleep(1200);
Mockito.verify(callBack).callFunc(captor.capture());
System.out.println(((JustAClass.JustAResultReal)captor.getValue()).content);
}
我知道我们可以添加一个sleep
来等待并期望子线程在这段时间内退出,但是还有更好的方法吗?实际上我怎么知道子线程需要多长时间?设置很长的时间可能是一种方法,但似乎不太好。
最佳答案
@stalet 的答案中的一般方法很接近,但不太有效,因为主线程不会注意到来自单独线程的任何断言失败。因此,您的测试将始终通过,即使它不应该通过。相反,请尝试使用 ConcurrentUnit (我创作):
@Test
public void testInvoke() throws Throwable {
Waiter waiter = new Waiter();
JustAClass justAClass = new JustAClass();
JustAClass.JustACallBack callBack = new JustAClass.JustACallBack() {
@Override
public void callFunc(final JustAClass.JustAResult result) {
waiter.assertNotNull(result);
waiter.assertTrue(result instanceof JustAClass.JustAResultReal);
waiter.resume();
}
};
justAClass.threadFunc(callBack);
waiter.await(1200, TimeUnit.SECONDS);
}
这里的关键是 ConcurrentUnit 的 Waiter
将正确向主测试线程报告任何断言失败,并且测试将按其应有的方式通过或失败。
关于java - 如何对java多线程进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33688787/