web-dev-qa-db-ja.com

同じメソッドを異なるパラメーターでモックする

私はビジネスサービスをテストするためにmockitoを使用していますが、モックしたいユーティリティを使用しています。異なる引数を持つユーティリティの各サービスメソッドには、少なくとも2〜3回の呼び出しがあります。

同じメソッドで異なる引数に対して複数のwhen(...).thenReturn(...)を使用する推奨方法はありますか?

内部でany() marcherも使用したいと思います。出来ますか?

更新:サンプルコード。

@Test
public void myTest() {
  when(service.foo(any(), new ARequest(1, "A"))).thenReturn(new AResponse(1, "passed"));
  when(service.foo(any(), new ARequest(2, "2A"))).thenReturn(new AResponse(2, "passed"));
  when(service.foo(any(), new BRequest(1, "B"))).thenReturn(new BResponse(112, "passed"));

  c.execute();
}

public class ClassUnderTest {
  Service service = new Service();
  public void execute() {
    AResponse ar = (AResponse) service.foo("A1", new ARequest(1, "A"));
    AResponse ar2 = (AResponse) service.foo("A2", new ARequest(2, "2A"));
    BResponse br = (BResponse) service.foo("B1", new BRequest(1, "B"));
  }
}

public class Service {
  public Object foo(String firstArgument, Object obj) {
    return null; //return something
  }
}
20
Zeeshan Bilal

1つの方法は、1つのthenReturn呼び出しだけですべての期待される結果を提供するために、引数を制限しすぎないようにすることです。

たとえば、このメソッドをモックしたいとしましょう:

public String foo(String firstArgument, Object obj) {
    return "Something";
}

次に、以下のように必要な数の結果を提供して、それをモックすることができます。

// Mock the call of foo of any String to provide 3 results
when(mock.foo(anyString(), anyObject())).thenReturn("val1", "val2", "val3");

パラメータを指定してfooを呼び出すと、それぞれ「val1 "、" val2」、その後の呼び出しは「val3 "。


渡された値を気にするが、呼び出しシーケンスに依存したくない場合は、thenAnswerを使用して、現在のように2番目の引数に一致するが、3つの異なるthenReturn

when(mock.foo(anyString(), anyObject())).thenAnswer(
    invocation -> {
        Object argument = invocation.getArguments()[1];
        if (argument.equals(new ARequest(1, "A"))) {
            return new AResponse(1, "passed");
        } else if (argument.equals(new ARequest(2, "2A"))) {
            return new AResponse(2, "passed");
        } else if (argument.equals(new BRequest(1, "B"))) {
            return new BResponse(112, "passed");
        }
        throw new InvalidUseOfMatchersException(
            String.format("Argument %s does not match", argument)
        );
    }
);
27
Nicolas Filotto

適切な方法は、eq()を使用して引数を一致させることですが、それを行いたくない場合は、複数の戻り値を記録できます。

when(someService.doSomething(any(SomeParam.class))).thenReturn(
  firstReturnValue, secondReturnValue, thirdReturnValue
);

これで、最初の呼び出しはfirstValue、2番目のsecondValue、およびそれに続くすべてのthirdValueを返します。

3

私は思う:「推奨」の方法はあなたのために働くものだろう。そして、それは最小限のコーディング努力でもたらされます。

テストを実行するために必要な仕様を提供する必要があります。それを回避する方法はありません。

使用する引数を本当に気にする場合は、それに応じて指定する必要があります。気にしない場合; any()を使用します。

0
Tom Bulgur