Mockito vérifie l'ordre / la séquence des appels de méthode

205

Existe-t-il un moyen de vérifier si un methodOneest appelé auparavant methodTwodans 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
la source

Réponses:

305

InOrder vous aide à le faire.

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
la source
5
C'est correct, bien que les appels à doNothing ne soient pas nécessaires ici, sauf en tant qu'espace réservé pour d'autres stubbing. Mockito acceptera silencieusement les appels de méthode void par défaut.
Jeff Bowman
1
Il les accepte alors que l'objet n'a pas de dépendances si l'objet a des dépendances il y aura une exception =)
Koitoer
14
considérer inOrder.verifyNoMoreInteractions();après la dernière vérification dans cet exemple pour vérifier qu'aucun autre appel n'a été effectué.
DwB
1
Juste pour clarifier: il est sûr de définir inOrder juste avant de vérifier - après avoir invoqué certaines méthodes (testées) sur des mocks.
user3078523
Les résultats sont-ils les mêmes pour inOrder(firstMock, secondMock)et inOrder(secondMock, firstMock)? Vous pouvez peut-être mettre à jour la réponse pour en faire une note.
kevinarpe
95

Notez que vous pouvez également utiliser la classe InOrder pour vérifier que diverses méthodes sont appelées dans l'ordre sur une seule maquette, et pas seulement sur deux ou plusieurs simulations.

Supposons que j'ai deux classes Fooet Bar:

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

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

Je peux alors ajouter une classe de test pour vérifier que Barde » firstThenSecond()la méthode appelle en fait first(), alors second(), et non second(), alors first(). Voir le code de test suivant:

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
la source
1
Cela aurait dû être un commentaire sur la réponse acceptée, pas une toute nouvelle réponse.
ach
12
Je suis en désaccord avec votre commentaire @ach L'exemple de code aide, donc une nouvelle réponse est logique.
Snekse
2
Existe-t-il un moyen de vérifier que la même méthode est appelée deux fois, mais de vérifier l'ordre des paramètres transmis? par exemple d'abord find('foo'), puisfind('bar')
Snekse
1
On dirait que cela pourrait être ma réponse stackoverflow.com/questions/36573399/…
Snekse
3
C'est en fait un meilleur exemple que la réponse acceptée car elle montre un usage plus typique quedoNothing()
Archimedes Trajano
37

Oui, cela est décrit dans la documentation. Vous devez utiliser la classe InOrder .

Exemple (en supposant que deux maquettes ont déjà été créées):

InOrder inOrder = inOrder(serviceAMock, serviceBMock);

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

Avec BDD c'est

@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();


}
Thrace
la source