问题是我有一个方法在启动一个新的线程,这是一个耗时的工作。我想测试回调结果,但是子线程可能还在运行,所以结果是,我得到的不是正确的存根。
我想密码可以解释:
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
来等待并期望子线程在该时间段内退出,但有没有更好的方法?实际上,我怎么知道子线程将花费多长时间?设置一个很长的时间可能是一种方法,但似乎不是很好。
2条答案
按热度按时间zu0ti5jz1#
@stalet的答案中的一般方法很接近,但并不完全有效,因为主线程不会注意到来自单独线程的任何Assert失败,因此您的测试总是通过,即使它不应该通过,而是尝试使用ConcurrentUnit(我编写的):
这里的关键是ConcurrentUnit的
Waiter
将正确地向主测试线程报告任何Assert失败,并且测试将按照它应该的方式通过或失败。dly7yett2#
我同意@Gimbys的评论,当您开始测试线程方面时,这不再是一个单元测试。
然而,作为一种集成测试异步调用的方法,它还是很有趣的。
为了避免睡眠,我倾向于使用类CountDownLatch来等待调用,为了倒计时,你需要一个回调接口的actuall实现--所以在我的例子中,我做了一个模拟实现。
由于没有实际的方法来获取数据-我只是测试它实际上是JustAreal接口的一个示例。