![](/img/trans.png)
[英]Unit test, how to test? wanted but not invoked on Mockito.verify
[英]Mockito verify fails in second unit test
我將Mockito與JUnit一起使用以實現Android項目中某個類的單元測試。問題是我在兩個隨后的測試中調用Mockito.verify
,它們的測試完全相同(以確保我正確使用了Mockito),但是有趣的是,第二個測試中的驗證總是會失敗。我懷疑在每次測試之前都需要使用@before
注釋或類似的東西進行一些操作,但我錯過了,這里有一些我正在做的代碼片段。
我使用Android Studio 3.4.1,Mockito 2.7.22和JUnit 4.12。
@Test
public void test_onStart_do_nothing() throws Exception {
ZConnectionService zConnectionService = new ZConnectionService();
ZConnection mockedZConnection = mock(ZConnection.class);
doNothing().when(mockedZConnection).connect();
zConnectionService.initConnection(mockedZConnection);
verify(mockedZConnection, times(1)).connect();
}
@Test
public void test_onStart_throw_IO_exceptioon() throws Exception {
ZConnectionService zConnectionService = new ZConnectionService();
ZConnection mockedZConnection = mock(ZConnection.class);
doNothing().when(mockedZConnection).connect();
zConnectionService.initConnection(mockedZConnection);
// Line above is the line that error message points to!
verify(mockedZConnection, times(1)).connect();
}
測試功能到了
public void initConnection(ZConnection connection) {
Log.d(TAG,"initConnection()");
if (mConnection == null) {
mConnection = connection;
}
if (!mActive) {
mActive = true;
if (mThread == null || !mThread.isAlive()) {
mThread = new Thread(new Runnable() {
@Override
public void run() {
// The code here runs in a background thread.
Looper.prepare();
mTHandler = new Handler();
try {
mConnection.connect();
} catch (IOException e) {
Intent i = null;
i = new Intent(ZConnectionService.UI_NOTCONNECTED);
i.setPackage(getApplicationContext().getPackageName());
getApplicationContext().sendBroadcast(i);
e.printStackTrace();
// Stop the services all together.
stopSelf();
}
Looper.loop();
}
});
mThread.start();
}
}
}
我希望兩項測試都可以順利通過。 實際上,當我分別運行它們時,兩個測試都通過了,但是當我運行整個套件時它們都失敗了,錯誤是:
Wanted but not invoked:
mockedZinkConnection.connect();
-> at com.app.z.ZConnectionServiceUnitTest.test_onStart_throw_IO_exceptioon(ZConnectionServiceUnitTest.java:207)
Actually, there were zero interactions with this mock.
我認為這個問題是多線程的。 當您調用initConnection
,它將在Thread
調用mConnection.connect()
。您遇到的問題是該Thread
需要一些時間才能完成,最終您會調用verify(mockedZConnection, times(1)).connect();
在線程實際到達connect()
調用之前。 確保它的一種方法是在啟動Thread
后將其加入,它將等待Thread
完成后再繼續:
mThread.start();
try {
mThread.join();
} catch (InterruptedException i) {
i.printStackTrace();
}
現在,這兩個測試都應該起作用。
當然這在代碼中是不可接受的,因為它否定了Thread
的使用。 您將需要其他方式進行測試。
我能想到的一種方法是在測試模擬之前等待線程完成測試:
@Test
public void test_onStart_throw_IO_exceptioon() throws Exception {
ZConnectionService zConnectionService = new ZConnectionService();
ZConnection mockedZConnection = mock(ZConnection.class);
doNothing().when(mockedZConnection).connect();
zConnectionService.initConnection(mockedZConnection);
// Wait for the Thread to complete
while(zConnectionService.mThread.isAlive()) {
Thread.sleep(100);
}
verify(mockedZConnection, times(1)).connect();
}
嘗試過,對我來說很好。 但不確定是否是最佳做法,因為您需要公開類的某些內部信息,這違反了封裝
也許在您的ZConnectionService
類上使用受保護的包isThreadAlive()
方法是可以接受的
boolean isThreadAlive() {
return mThread.isAlive();
}
和測試中的循環
while(zConnectionService.isThreadAlive()) {
Thread.sleep(100);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.