Respostas:
Eu concordo com o que o @fge disse, muito mais. Vamos ver o exemplo. Considere que você tem um método:
class A {
public void foo(OtherClass other) {
SomeData data = new SomeData("Some inner data");
other.doSomething(data);
}
}
Agora, se você deseja verificar os dados internos, pode usar o capttor:
// 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);
OtherClass
é uma farsa e, como está definido agora, doSomething()
ele não fará nada, simplesmente registra o objeto que foi passado. Isso significa que ele será capturado como está antes de doSomething
ser executado.
verify
, times(1)
é o padrão e pode ser omitido.
verify
método, ele usa essas informações para executar correspondências na verificação que você está fazendo. Para cada parâmetro, ele pergunta se corresponde à chamada específica que verifica. Quando o ArgumentCaptor está marcado, ele simplesmente armazena os valores com os quais foi chamado e, quando verify
termina, mantém todas as chamadas relevantes. É mais ou menos assim que funciona. Espero que ajude
As duas principais diferenças são:
ArgumentCaptor
pode capturar mais de uma vez.Para ilustrar o último, diga que você tem:
final ArgumentCaptor<Foo> captor = ArgumentCaptor.forClass(Foo.class);
verify(x, times(4)).someMethod(captor.capture()); // for instance
Em seguida, o captador poderá fornecer acesso a todos os 4 argumentos, nos quais você poderá executar asserções separadamente.
Este ou qualquer número de argumentos, de fato, uma vez que a VerificationMode
não se limita a um número fixo de invocações; de qualquer forma, o seqüestrador lhe dará acesso a todos eles, se desejar.
Isso também tem o benefício de que esses testes são (mais) muito mais fáceis de escrever do que ter que implementar seus próprios ArgumentMatcher
s - principalmente se você combinar mockito com assertj.
Ah, e considere usar o TestNG em vez do JUnit.
As etapas para fazer uma verificação completa são:
Prepare o seqüestrador:
ArgumentCaptor<SomeArgumentClass> someArgumentCaptor = ArgumentCaptor.forClass(SomeArgumentClass.class);
verifique se a chamada para dependente do componente (colaborador do sujeito em teste) vezes (1) é o valor padrão, portanto, não é necessário adicioná-lo.
verify(dependentOnComponent, times(1)).send(someArgumentCaptor.capture());
Obter o argumento passado para o colaborador
SomeArgumentClass someArgument = messageCaptor.getValue();
someArgument pode ser usado para asserções
Aqui, estou fornecendo um exemplo adequado de um método de retorno de chamada. então suponha que tenhamos um método como o método 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");
}
Também coloquei toda a classe auxiliar aqui para tornar o exemplo mais claro: 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);
}}
e temos o ouvinte LoginListener como:
interface LoginListener {
void onLoginSuccess();
void onLoginFaliure();
}
agora eu só queria testar o método login () da 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);
Também não se esqueça de adicionar anotações acima da classe de teste,
@RunWith(PowerMockRunner.class)
@PrepareForTest(Login.class)
captor
definido na sua resposta?
doSomething(data)
mutaçãoinnerData
, essa alteração estará presenteassertEquals("Some inner data", actual.innerData)
ou seráinnerData
capturada como está antes dedoSomething
ser executada?