web-dev-qa-db-ja.com

Mockito 2を使用したサービスのシミュレーションにより、スタブエラーが発生する

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を使用してテストを実行すると、同じ結果になります。

12
aschoerk

厳密なスタブ(Mockitoのデフォルトの動作)では、同じメソッドでいくつかのwhensを呼び出すと、そのモックがリセットされます。解決策は、whenonceを呼び出し、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 {
11
Mureinik

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));
  }
}
8
aschoerk