web-dev-qa-db-ja.com

Mockito argumentCaptorの例

org.mockito.ArgumentCaptorクラスの使い方と、mockitoで提供されているsimple matcherとの違いを示す例を誰でも教えてください。

提供されているmockitoの文書を読みましたが、明確には説明されていません。明確に説明することもできません。

90
Ujjwal

私は@fgeが言ったことに同意します。例を見てみましょう。方法があるとします。

class A {
    public void foo(OtherClass other) {
        SomeData data = new SomeData("Some inner data");
        other.doSomething(data);
    }
}

内部データを確認したい場合は、今度はcaptorを使用します。

// Create a mock of the OtherClass
OtherClass other = mock(OtherClass.class);

// Run the foo method with the mock
new A().foo(other);

// Capture the argument of the doSomething function
ArgumentCaptor<SomeData> captor = ArgumentCaptor.forClass(SomeData.class);
verify(other, times(1)).doSomething(captor.capture());

// Assert the argument
SomeData actual = captor.getValue();
assertEquals("Some inner data", actual.innerData);
125
Slava Shpitalny

主な違いは2つあります。

  • 単一の引数でさえ捕らえれば、この引数について、そしてより明白なコードを使って、もっと複雑なテストをすることができます。
  • ArgumentCaptormoreを複数回捕捉することができます。

後者を説明するために、あなたが持っていると言う:

final ArgumentCaptor<Foo> captor = ArgumentCaptor.forClass(Foo.class);

verify(x, times(4)).someMethod(captor.capture()); // for instance

そうすれば、キャプターは4つの引数すべてにアクセスできるようになります。その後、それらを個別にアサーションを実行できます。

VerificationModeは固定数の呼び出しに制限されていないため、実際にはこの数または任意の数の引数。いずれにせよ、あなたが望むならば、キャプターはあなたにそれらの全てへのアクセスをあなたに与えるでしょう。

これには、特にmockitoとassertjを組み合わせる場合は、独自のArgumentMatchersを実装する必要がある場合よりも、このようなテストの作成がはるかに簡単になるという利点もあります。

そう、JUnitの代わりにTestNGを使うことを検討してください。

27
fge

完全なチェックをするためのステップは次のとおりです。

キャプターを準備します。

ArgumentCaptor<SomeArgumentClass> someArgumentCaptor = ArgumentCaptor.forClass(SomeArgumentClass.class);

コンポーネント依存(テスト対象の共同作業者)回(1)への呼び出しがデフォルト値であることを確認します。それを追加する必要があります。

verify(dependentOnComponent, times(1)).send(someArgumentCaptor.capture());

共同編集者に渡された引数を取得する

SomeArgumentClass someArgument = messageCaptor.getValue();

someArgumentはアサーションに使用できます

3
Lho Ben

ここでは、1つのコールバックメソッドの適切な例を紹介します。メソッドlogin()のようなメソッドがあるとします。

 public void login() {
    loginService = new LoginService();
    loginService.login(loginProvider, new LoginListener() {
        @Override
        public void onLoginSuccess() {
            loginService.getresult(true);
        }

        @Override
        public void onLoginFaliure() {
            loginService.getresult(false);

        }
    });
    System.out.print("@@##### get called");
}

例をより明確にするために、ここにすべてのヘルパークラスも入れています。

public class LoginService implements Login.getresult{
public void login(LoginProvider loginProvider,LoginListener callback){

    String username  = loginProvider.getUsername();
    String pwd  = loginProvider.getPassword();
    if(username != null && pwd != null){
        callback.onLoginSuccess();
    }else{
        callback.onLoginFaliure();
    }

}

@Override
public void getresult(boolean value) {
    System.out.print("login success"+value);
}}

リスナーLoginListenerは次のようになります。

interface LoginListener {
void onLoginSuccess();

void onLoginFaliure();

}

今私はちょうどクラスLoginのメソッドlogin()をテストしたいと思いました

 @Test
public void loginTest() throws Exception {
    LoginService service = mock(LoginService.class);
    LoginProvider provider = mock(LoginProvider.class);
    whenNew(LoginProvider.class).withNoArguments().thenReturn(provider);
    whenNew(LoginService.class).withNoArguments().thenReturn(service);
    when(provider.getPassword()).thenReturn("pwd");
    when(provider.getUsername()).thenReturn("username");
    login.getLoginDetail("username","password");

    verify(provider).setPassword("password");
    verify(provider).setUsername("username");

    verify(service).login(eq(provider),captor.capture());

    LoginListener listener = captor.getValue();

    listener.onLoginSuccess();

    verify(service).getresult(true);

また、テストクラスの上にアノテーションを追加することを忘れないでください。

@RunWith(PowerMockRunner.class)
@PrepareForTest(Login.class)
0
Vikram singh