問題是我有一個方法開始一個耗時的工作的新線程。我想測試回調結果,但子線程可能仍在運行,因此,我得到的不是正確的存根。
我覺得代碼可以解釋本身:
如何單元測試java多線程
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
等待,期望子線程會在這段時間內退出,但是有沒有更好的方法?其實我怎麼知道子線程需要多長時間?設置很長時間可以是一種方法,但看起來不是很好。
IMO:我會從單元測試中刪除自己的線程方面,並測試線程內部的邏輯。我相信Java中的線程工作原理,我不需要測試它。並且測試邏輯的線程對於你並行運行的代碼的工作方式是集成測試的一部分,而不是單元測試。 – Gimby
問題是,您正在使用靜態ExecutorService。爲了使事情更加單元化,您可以傳入_mock_ ExecutorService,然後驗證被測模塊是否以預期方式與模擬進行了交互。 –
如果線程是您正在測試的代碼的*點,那麼在單元測試中進行線程沒有什麼問題。請參閱我的答案,瞭解如何正確執行此操作。 – Jonathan