web-dev-qa-db-fra.com

Exemple d'argument de MockitoCaptor

Quelqu'un peut-il me donner un exemple illustrant l’utilisation de la classe org.mockito.ArgumentCaptor et en quoi elle diffère de simples correspondants fournis avec mockito.

J'ai lu les documents Mockito fournis mais ceux-ci ne l'illustrent pas clairement, ils ne sont pas non plus capables de l'expliquer avec clarté.

101
Ujjwal

Je suis d’accord avec ce que @fge a dit, encore plus. Regardons l'exemple. Considérez que vous avez une méthode:

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

Maintenant, si vous voulez vérifier les données internes, vous pouvez utiliser le capteur:

// 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);
137
Slava Shpitalny

Les deux principales différences sont les suivantes:

  • lorsque vous capturez même un seul argument, vous pouvez effectuer des tests beaucoup plus élaborés sur cet argument, avec un code plus évident;
  • un ArgumentCaptor peut capturer plus qu'une fois.

Pour illustrer ce dernier, disons que vous avez:

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

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

Ensuite, le capteur pourra vous donner accès aux 4 arguments sur lesquels vous pourrez ensuite effectuer des assertions séparément.

Ceci ou un certain nombre d'arguments en fait, car une VerificationMode n'est pas limitée à un nombre fixe d'invocations; dans tous les cas, le ravisseur vous donnera accès à tous, si vous le souhaitez.

Cela présente également l'avantage que ces tests sont (à mon humble avis) beaucoup plus faciles à écrire que d'avoir à implémenter vos propres ArgumentMatchers - en particulier si vous combinez mockito avec assertj.

Oh, et envisagez d'utiliser TestNG au lieu de JUnit.

28
fge

Les étapes pour effectuer une vérification complète sont les suivantes:

Préparez le ravisseur:

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

vérifier l'appel à dépendre du composant (collaborateur du sujet testé) fois (1), est la valeur par défaut, il n'est donc pas nécessaire de l'ajouter.

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

Obtenir l'argument passé au collaborateur

SomeArgumentClass someArgument = messageCaptor.getValue();

someArgument peut être utilisé pour des assertions

4
Lho Ben

Ici, je vous donne un exemple approprié d'une méthode de rappel. supposons donc que nous ayons une méthode comme méthode 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");
}

J'ai également mis toute la classe d'assistance ici pour rendre l'exemple plus clair: classe loginService

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

et nous avons listener LoginListener en tant que:

interface LoginListener {
void onLoginSuccess();

void onLoginFaliure();

}

maintenant je voulais juste tester la méthode login () de la classe 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);

n'oubliez pas d'ajouter une annotation au-dessus de la classe de test

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