我正在使用 JUnit 4 和 Mockito 4.6.1 撰寫單元測驗。我正在模擬具有特定輸入值的介面方法。當傳遞一個不同的值時,我期待一個引數不匹配錯誤,但它沒有被拋出。
考慮以下示例:
public class SomeTest {
@Test
public void test() {
SomeInterface mock = Mockito.mock(SomeInterface.class, Mockito.withSettings().strictness(Strictness.STRICT_STUBS));
// Only mock test(true) and not test(false).
Mockito.when(mock.test(true)).thenReturn(1);
Assert.assertEquals(mock.test(true), 1);
Assert.assertEquals(
// Expecting argument mismatch error
mock.test(false),
2
);
}
interface SomeInterface {
int test(Boolean arg);
}
}
我嘲笑SomeInterface.test(true)回傳 1。這按預期作業。現在當我呼叫時mock.test(false),我期待引數不匹配,因為它沒有在模擬設定中定義并且啟用了嚴格模式。相反,它回傳 0 就好像它被模擬了一樣。
我錯過了導致這種情況發生的事情嗎?
uj5u.com熱心網友回復:
問題 1.我們必須啟用STRICT_STUBS進行測驗。
STRICT_STUBS - 確保干凈的測驗,減少測驗代碼重復,提高可除錯性。靈活性和生產力的最佳組合。強烈推薦。計劃為 Mockito v4 的默認設定。通過 MockitoRule、MockitoJUnitRunner 或 MockitoSession 啟用它。有關詳細資訊,請參閱 STRICT_STUBS。
根據檔案,它可以通過MockitoJUnitRunner.StrictStubs.class完成
@RunWith(MockitoJUnitRunner.StrictStubs.class)
或嚴格規則
@Rule public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
問題 2.當模擬定義和模擬呼叫在一個源類中執行時,引數嚴格性不起作用。
根據 Mockito源代碼:
如果存根和呼叫在同一個源檔案中,我們假設它們在測驗代碼中,并且我們不會將其標記為不匹配:
總結。作業測驗將是:
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.quality.Strictness;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.StrictStubs.class)
public class SomeTest {
@Test
public void test() {
SomeInterface mock = Mockito.mock(SomeInterface.class, withSettings().strictness(Strictness.STRICT_STUBS));
Mockito.when(mock.test(true)).thenReturn(1);
SomeInterfaceImpl someInterface = new SomeInterfaceImpl(mock);
Assert.assertEquals(someInterface.test(), 2);
}
}
public interface SomeInterface {
int test(Boolean arg);
}
public class SomeInterfaceImpl {
private SomeInterface someInterface;
public SomeInterfaceImpl(SomeInterface someInterface) {
this.someInterface = someInterface;
}
public int test() {
return someInterface.test(false);
}
}
在執行時,我們得到:
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'test' method:
someInterface.test(false);
-> at com.example.SomeInterfaceImpl.test(SomeInterfaceImpl.java:10)
- has following stubbing(s) with different arguments:
1. someInterface.test(true);
-> at com.example.SomeTest.test(SomeTest.java:26)
Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
However, there are legit scenarios when this exception generates false negative signal:
- stubbing the same method multiple times using 'given().will()' or 'when().then()' API
Please use 'will().given()' or 'doReturn().when()' API for stubbing.
- stubbed method is intentionally invoked with different arguments by code under test
Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).
For more information see javadoc for PotentialStubbingProblem class.
更可取的解決方案
您可以為您的模擬定義默認答案,IllegalArgumentException以防模擬使用不匹配的引數執行。此解決方案將始終有效,不受源檔案限制。
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.doReturn;
@RunWith(MockitoJUnitRunner.class)
public class SomeTest {
@Test
public void test() {
SomeInterface mock = Mockito.mock(SomeInterface.class, Mockito.withSettings().defaultAnswer(
invocation -> {
throw new IllegalArgumentException(String.format("You cannot invoke %s with %s", invocation.getMethod(), java.util.Arrays.toString(invocation.getArguments())));
}
));
// Only mock test(true) and not test(false).
doReturn(1).when(mock).test(true);
Assert.assertEquals(mock.test(true), 1);
Assert.assertEquals(
// Expecting argument mismatch error
mock.test(false),
2
);
}
}
在執行時,我們得到:
java.lang.IllegalArgumentException: You cannot invoke public abstract int com.example.SomeInterface.test(java.lang.Boolean) with [false]
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/488723.html
下一篇:使原始鏈接的可執行目錄可訪問
