Mockitoを使用して、クラスの動作をシミュレートしようとしています。これはMockito 1.xを使用して機能しました。 JUnit 5とMockito 2に移行すると、もう機能しないようです。
@ExtendWith(MockitoExtension.class)
public class MockitoExample {
static abstract class TestClass {
public abstract int booleanMethod(boolean arg);
}
@Mock
TestClass testClass;
@BeforeEach
public void beforeEach() {
when(testClass.booleanMethod(eq(true))).thenReturn(1);
when(testClass.booleanMethod(eq(false))).thenReturn(2);
}
@Test
public void test() {
assertEquals(1,testClass.booleanMethod(true));
assertEquals(2,testClass.booleanMethod(false));
}
}
模擬テストクラスがテストメソッドでテストされた動作を示すことが期待されます。
私が得るエラーは次のとおりです:
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'booleanMethod' method:
testClass.booleanMethod(false);
-> at org.oneandone.ejbcdiunit.mockito_example.MockitoExample.beforeEach(MockitoExample.Java:30)
- has following stubbing(s) with different arguments:
1. testClass.booleanMethod(false);
-> at org.oneandone.ejbcdiunit.mockito_example.MockitoExample.beforeEach(MockitoExample.Java:29)
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.
どちらの場合も、引数false
は一致しているように見えますが、true
と明確に一致しています。
それはMockito 2.17のバグか誤解ですか。 Mockito 2.xを使用して、異なるブール引数を持つ呼び出しをシミュレートするにはどうすればよいですか?
example はgithubにもあります。ただし、surefireはテストを開始するときにのみ使用します
mvn test -Dtest=MockitoExample
Mockito 2.21を使用してテストを実行すると、同じ結果になります。
厳密なスタブ(Mockitoのデフォルトの動作)では、同じメソッドでいくつかのwhen
sを呼び出すと、そのモックがリセットされます。解決策は、when
onceを呼び出し、Answer
にロジックを含めることです。
@BeforeEach
public void beforeEach() {
when(testClass.booleanMethod(anyBoolean())).thenAnswer(invocationOnMock -> {
if ((boolean) invocationOnMock.getArguments()[0]) {
return 1;
}
return 2;
});
}
あるいは、寛大なモックを使用することもできますが、それは常に良いアイデアではありません-寛大なモックは冗長なスタブを可能にし、テストで間違いを犯しやすくします。
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class MockitoExample {
Mockito 2.20以降では、lenient()をローカルに追加することも可能です
@ExtendWith(MockitoExtension.class)
public class MockitoExample {
static abstract class TestClass {
public abstract int booleanMethod(boolean arg);
}
@Mock
TestClass testClass;
@BeforeEach
public void beforeEach() {
lenient().when(testClass.booleanMethod(eq(true))).thenReturn(1);
lenient().when(testClass.booleanMethod(eq(false))).thenReturn(2);
}
@Test
public void test() {
assertEquals(1,testClass.booleanMethod(true));
assertEquals(2,testClass.booleanMethod(false));
}
}