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é.
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);
Les deux principales différences sont les suivantes:
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 ArgumentMatcher
s - en particulier si vous combinez mockito avec assertj.
Oh, et envisagez d'utiliser TestNG au lieu de JUnit.
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
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)