解決 Mockito 異常:需要但未調用
一、概述
在本教程中,我們將討論使用 Mockito 時可能遇到的常見錯誤。 Exception
消息是:
Wanted but not invoked:
// class name and location
Actually, there were zero interactions with this mock.
讓我們了解此錯誤的潛在來源以及如何修復它。
2. 示例設置
首先,讓我們創建我們稍後要模擬的類。它包含一個單獨的方法,它總是返回String
, “Baeldung”
:
class Helper {
String getBaeldungString() {
return "Baeldung";
}
}
現在讓我們創建我們的主類。它在類級別聲明一個Helper
實例。我們想在單元測試期間模擬這個實例:
class Main {
Helper helper = new Helper();
String methodUnderTest(int i) {
if (i > 5) {
return helper.getBaeldungString();
}
return "Hello";
}
}
最重要的是,我們定義了一個接受Integer
作為參數並返回的方法:
- 如果
Integer
大於 5,調用getBaeldunString()
的結果 - 如果
Integer
小於或等於 5,則為常量
3.調用真正的方法而不是模擬
讓我們嘗試為我們的方法編寫單元測試。我們將使用@Mock
註釋來創建模擬的Helper
。我們還將調用MockitoAnnotations.openMocks()
來啟用 Mockito 註釋。在測試方法中,我們將使用參數7
調用methodUnderTest()
並檢查它是否委託給getBaeldungString()
:
class MainUnitTest {
@Mock
Helper helper;
Main main = new Main();
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
void givenValueUpperThan5_WhenMethodUnderTest_ThenDelegatesToHelperClass() {
main.methodUnderTest(7);
Mockito.verify(helper)
.getBaeldungString();
}
}
現在讓我們運行我們的測試:
Wanted but not invoked:
helper.getBaeldungString();
-> at com.baeldung.wantedbutnotinvocked.Helper.getBaeldungString(Helper.java:6)
Actually, there were zero interactions with this mock.
問題是我們調用了構造函數來實例化一個Main
對象。因此, Helper
實例是通過調用new()
創建的。因此,我們使用真正的Helper
對象而不是我們的模擬對象。要解決這個問題,我們需要在我們的Main
對象創建之上添加@InjectMocks
:
@InjectMocks
Main main = new Main();
作為旁注,如果我們在methodUnderTest()
的任何點用真實對象替換模擬實例,我們將再次陷入同樣的問題:
String methodUnderTest(int i) {
helper = new Helper();
if (i > 5) {
return helper.getBaeldungString();
}
return "Hello";
}
簡而言之,我們這裡有兩個注意點:
- 應該正確創建和注入模擬。
- 在任何時候都不應將模擬對象替換為其他對象。
4.方法未被調用
我們現在將編寫一個新的單元測試。它將檢查將3
作為參數傳遞給methodUnderTest()
是否會調用getBaeldungString()
:
@Test
void givenValueLowerThan5_WhenMethodUnderTest_ThenDelegatesToGetBaeldungString() {
main.methodUnderTest(3);
Mockito.verify(helper)
.getBaeldungString();
}
再一次,我們可以運行測試:
Wanted but not invoked:
helper.getBaeldungString();
-> at com.baeldung.wantedbutnotinvocked.Helper.getBaeldungString(Helper.java:6)
Actually, there were zero interactions with this mock.
這次,讓我們仔細閱讀錯誤信息。它說我們沒有與模擬交互。現在讓我們回顧一下我們的方法規範: 3
小於5
,因此methodUnderTest()
返回一個常量而不是委託給getBaeldungString()
。因此,我們的測試與規範相矛盾。
在這種情況下,我們只有兩種可能的結論:
- 規範是正確的:我們需要修復我們的測試,因為驗證是無用的。
- 測試是正確的:我們的代碼中有一個錯誤需要解決。
5.結論
在本文中,我們在沒有與模擬交互的情況下調用Mockito.verify()
並出現錯誤。我們指出我們需要正確地註入和使用模擬。我們還看到這個錯誤是在不連貫的測試中出現的。
與往常一樣,代碼在 GitHub 上可用。