Mockito verificar a ordem / sequência de chamadas de método

205

Existe uma maneira de verificar se a methodOneé chamada anteriormente methodTwono Mockito?

public class ServiceClassA {
    public void methodOne(){}
 }

public class ServiceClassB {
    public void methodTwo(){}
 }

public class TestClass {
    public void method(){
        ServiceClassA serviceA = new ServiceClassA();
        ServiceClassB serviceB = new ServiceClassB();
        serviceA.methodOne();
        serviceB.methodTwo();
    }
}
froi
fonte

Respostas:

305

InOrder ajuda você a fazer isso.

ServiceClassA firstMock = mock(ServiceClassA.class);
ServiceClassB secondMock = mock(ServiceClassB.class);

Mockito.doNothing().when(firstMock).methodOne();   
Mockito.doNothing().when(secondMock).methodTwo();  

//create inOrder object passing any mocks that need to be verified in order
InOrder inOrder = inOrder(firstMock, secondMock);

//following will make sure that firstMock was called before secondMock
inOrder.verify(firstMock).methodOne();
inOrder.verify(secondMock).methodTwo();
Koitoer
fonte
5
Isso está correto, embora as chamadas para doNothing não sejam necessárias aqui, exceto como um espaço reservado para outras stub. O Mockito aceita silenciosamente chamadas de método nulas por padrão.
22614 Jeff Bowman
1
É aceitá-los enquanto o objecto não têm dependências, se o objecto tem dependências haverá uma excepção =)
Koitoer
14
considere inOrder.verifyNoMoreInteractions();após a última verificação neste exemplo para verificar se nenhuma outra chamada foi feita.
DWB
1
Apenas para esclarecer: É seguro definir o inOrder imediatamente antes da verificação - depois de chamar alguns métodos (testados) nas zombarias.
user3078523
Os resultados são os mesmos para inOrder(firstMock, secondMock)e inOrder(secondMock, firstMock)? Talvez você possa atualizar a resposta para fazer uma anotação sobre isso.
Kevinarpe
95

Observe que você também pode usar a classe InOrder para verificar se vários métodos são chamados em ordem em uma única simulação, não apenas em duas ou mais zombarias.

Suponha que eu tenha duas classes Fooe Bar:

public class Foo {
  public void first() {}
  public void second() {}
}

public class Bar {
  public void firstThenSecond(Foo foo) {
    foo.first();
    foo.second();
  }
}

Posso, então, adicionar uma classe de teste para teste que Bar's firstThenSecond()método realmente chama first(), então second(), e não second(), então first(). Veja o seguinte código de teste:

public class BarTest {
  @Test
  public void testFirstThenSecond() {
    Bar bar = new Bar();
    Foo mockFoo = Mockito.mock(Foo.class);
    bar.firstThenSecond(mockFoo);

    InOrder orderVerifier = Mockito.inOrder(mockFoo);
    // These lines will PASS
    orderVerifier.verify(mockFoo).first();
    orderVerifier.verify(mockFoo).second();

    // These lines will FAIL
    // orderVerifier.verify(mockFoo).second();
    // orderVerifier.verify(mockFoo).first();
  }
}
entpnerd
fonte
1
Isso deveria ter sido um comentário sobre a resposta aceita, não uma resposta totalmente nova.
ach
12
Não concordo com o seu comentário @ach O exemplo de código ajuda, portanto uma nova resposta faz sentido.
Snekse
2
Existe uma maneira de verificar se o mesmo método é chamado duas vezes, mas verificar a ordem dos parâmetros passados? por exemplo find('foo'), primeiro , entãofind('bar')
Snekse 14/04
1
Parece que este poderia ser a minha resposta stackoverflow.com/questions/36573399/...
Snekse
3
Este é realmente um exemplo melhor do que a resposta aceita, porque mostra um uso mais típico do quedoNothing()
Archimedes Trajano
37

Sim, isso está descrito na documentação. Você precisa usar a classe InOrder .

Exemplo (assumindo duas zombarias já criadas):

InOrder inOrder = inOrder(serviceAMock, serviceBMock);

inOrder.verify(serviceAMock).methodOne();
inOrder.verify(serviceBMock).methodTwo();
LaurentG
fonte
1

Com o BDD, é

@Test
public void testOrderWithBDD() {


    // Given
    ServiceClassA firstMock = mock(ServiceClassA.class);
    ServiceClassB secondMock = mock(ServiceClassB.class);

    //create inOrder object passing any mocks that need to be verified in order
    InOrder inOrder = inOrder(firstMock, secondMock);

    willDoNothing().given(firstMock).methodOne();
    willDoNothing().given(secondMock).methodTwo();

    // When
    firstMock.methodOne();
    secondMock.methodTwo();

    // Then
    then(firstMock).should(inOrder).methodOne();
    then(secondMock).should(inOrder).methodTwo();


}
Trácia
fonte