web-dev-qa-db-ja.com

Mockito Matchers isA、any、eq、およびsameの違いは何ですか?

それらの違いは何で、どの場合にどちらを選択するのか混乱しています。 anyeqのように、いくつかの違いは明らかかもしれませんが、念のためにそれらをすべて含めています。

私はこの問題に遭遇したので、彼らの違いについて疑問に思います:私はこれを持っていますPOST Controllerクラスのメソッド

_public Response doSomething(@ResponseBody Request request) {
    return someService.doSomething(request);
}
_

そして、そのコントローラーで単体テストを実行したいと思います。 2つのバージョンがあります。最初のものはこのようにシンプルなものです

_@Test
public void testDoSomething() {
    //initialize ObjectMapper mapper
    //initialize Request req and Response res

    when(someServiceMock.doSomething(req)).thenReturn(res);

    Response actualRes = someController.doSomething(req);
    assertThat(actualRes, is(res));
}
_

しかし、私はこのようなMockMvcアプローチを使用したかった

_@Test
public void testDoSomething() {
    //initialize ObjectMapper mapper
    //initialize Request req and Response res

    when(someServiceMock.doSomething(any(Request.class))).thenReturn(res);

    mockMvc.perform(post("/do/something")
            .contentType(MediaType.APPLICATION_JSON)
            .content(mapper.writeValueAsString(req))
    )
            .andExpect(status().isOk())
            .andExpect(jsonPath("$message", is("done")));
}
_

両方ともうまくいきます。しかし、MockMvcアプローチのsomeServiceMock.doSomething()req、または少なくともreqと同じ変数値を持つオブジェクト(Request class)、およびresを返します。最初と同様です。実際の呼び出しで渡されるオブジェクトは、モックで渡されるオブジェクトと常に異なるため、MockMvcアプローチを使用することは不可能であることを知っています(またはそうですか?)。とにかくそれを達成することができますか?それとも、それをするのも理にかなっていますか?または、any(Request.class)を使用して満足する必要がありますか? eqsameを試しましたが、すべて失敗します。

前もって感謝します。私は自分自身をうまく説明したいと思います。

33
Silly Sally
  • any()は何もチェックしません。 Mockito 1.xでは、any(T.class)もまったくチェックしませんが、キャストを保存します(Java 8)より前)。

    これはMockito 2.0以降の変更によるany(T.class)isAセマンティクスを共有して「any T」または適切に「anyタイプT "のインスタンス。 any()はまだ何もチェックしません。

  • isA(T.class)は、引数_instanceof T_がnullでないことを意味することを確認します。

  • same(obj)は、引数がobjと同じインスタンスであること、つまり_arg == obj_がtrueであることを確認します。

  • eq(obj)は、objメソッドに従って、引数がequalsに等しいことを確認します。これは、マッチャーを使用せずに実際の値を渡す場合の動作でもあります。

    equalsがオーバーライドされない限り、デフォルトのObject.equals実装が表示され、same(obj)と同じ動作になることに注意してください。

より正確なカスタマイズが必要な場合は、独自の述語にアダプターを使用できます。

  • Mockito 1.xでは、必要なオブジェクトを正確に選択するカスタムHamcrest _Matcher<T>_でargThatを使用します。
  • Mockito 2.0以降では、カスタム_Matchers.argThat_で_org.mockito.ArgumentMatcher<T>_を使用するか、カスタムHamcrest _MockitoHamcrest.argThat_で_Matcher<T>_を使用します。
64
Jeff Bowman

Request.classがequalsを実装している場合、eq()を使用できます。

Bar bar = getBar();
when(fooService.fooFxn(eq(bar)).then...

上記のwhenが有効になります

fooService.fooFxn(otherBar);

もし

otherBar.equals(bar);

または、モックを入力の他のサブセット(たとえば、Bar.getBarLength()> 10を持つすべてのバー)で動作させたい場合は、Matcherを作成できます。このパターンはあまり頻繁に見られないので、通常、Matcherをプライベートクラスとして作成します。

private static class BarMatcher extends BaseMatcher<Bar>{
...//constructors, descriptions, etc.
  public boolean matches(Object otherBar){
     //Checks, casts, etc.
     return otherBar.getBarLength()>10;
  }
}

次に、このマッチャーを次のように使用します。

when(fooService.fooFxn(argThat(new BarMatcher())).then...

お役に立てば幸いです!

3
Alex Pruss