2016-07-13 1 views
0

Je crée un test unitaire pour montrer que deux méthodes s'exécutent en parallèle. Pour cela, je me moque des deux méthodes et les deux ont un retard de 2 secondes. Je valide alors le test unitaire à moins de 4 (donc je peux être sûr que les actions ne sont pas exécutées séquentiellement car cela prendrait alors plus de 4 [2 * 2] secondes).Les méthodes de validation s'exécutent en parallèle

Y a-t-il un meilleur moyen?

+1

début du journal et à la fin de la maquette. Les deux devraient commencer avant chaque fin, et vous pouvez utiliser les entrées du journal pour vérifier cela (ou incrémenter une variable partagée - atomiquement! - quand la tâche commence, décrémenter quand elle se termine, garder une trace de son maximum, et vérifier la réponse est deux) . Etc. –

+0

Les deux méthodes proviennent-elles du même simulacre? –

+0

@LorenzoMurrocu nous aimerions soutenir les deux situations. Même simulacre et différent. –

Répondre

1

J'utiliserais la fonction InOrder. Voici un exemple pour le cas, les deux méthodes sont de la même maquette:

@Test 
public void foo() { 
    MyClass mock = Mockito.mock(MyClass.class); 
    Mockito.when(mock.methodOne())thenAnswer(new Answer<ReturnType>() 
    { 

     @Override 
     public ReturnType answer(InvocationOnMock invocation) throws Throwable 
     { 
      // Implement the delay or parallel execution 
      . . . 
      mock.methodThree(); // This invocation is just a hook to intercept the end of this method execution 
      return something; 
     } 
    }); 

    Mockito.when(mock.methodTwo())thenAnswer(new Answer<ReturnType>() 
    { 

     @Override 
     public ReturnType answer(InvocationOnMock invocation) throws Throwable 
     { 
      // Implement the delay or the parallel execution 
      . . . 
      mock.methodThree(); // This invocation is just a hook to intercept the end of this method execution 
      return something; 
     } 
    }); 



    // Here there should be the call to the real method that calls the two methods in parallel: 
    // !!HERE!! 
    // mock1.methodOne(); 
    // mock2.methodTwo(); 

    InOrder inOrder = Mockito.inOrder(mock1, mock2); 
    inOrder.verify(mock1).methodOne(); //asserts that methodOne should be invoked first 
    inOrder.verify(mock2).methodTwo(); //asserts that methodTwo should be invoked after methodOne 
    inOrder.verify(mock3, Mockito.calls(2)).methodThree(); //asserts that methodThree, that is invoked at the end of methodOne, is invoked after the methodTwo invocation. These asserts together tell us that methodTwo was called during the execution of methodOne. 
} 

Vous pouvez utiliser le afinde aussi avec plusieurs simulacres:

@Test 
public void foo() { 
    MyClass mock1 = Mockito.mock(MyClass.class); 
    MyClass mock2 = Mockito.mock(MyClass.class); 
    OtherClass mock3 = Mockito.mock(OtherClass.class); 

    Mockito.when(mock1.methodOne())thenAnswer(new Answer<ReturnType>() 
    { 

     @Override 
     public ReturnType answer(InvocationOnMock invocation) throws Throwable 
     { 
      // Implement the delay or the parallel execution 
      . . . 
      mock3.methodThree(); // This invocation is just a hook to intercept the end of this method execution 
      return something; 
     } 
    }); 

    Mockito.when(mock2.methodTwo())thenAnswer(new Answer<ReturnType>() 
    { 

     @Override 
     public ReturnType answer(InvocationOnMock invocation) throws Throwable 
     { 
      // Implement the delay or the parallel execution 
      . . . 
      mock3.methodThree(); // This invocation is just a hook to intercept the end of this method execution 
      return something; 
     } 
    }); 


    // Here there should be the call to the real method that calls the two methods in parallel: 
    // !!HERE!! 
    // mock1.methodOne(); 
    // mock2.methodTwo(); 

    InOrder inOrder = Mockito.inOrder(mock1, mock2); 
    inOrder.verify(mock1).methodOne(); //asserts that methodOne should be invoked first 
    inOrder.verify(mock2).methodTwo(); //asserts that methodTwo should be invoked after methodOne 
    inOrder.verify(mock3, Mockito.calls(2)).methodThree(); //asserts that methodThree, that is invoked at the end of methodOne, is invoked after the methodTwo invocation. These asserts together tell us that methodTwo was called during the execution of methodOne. 
} 

Dans cet exemple, mock3 est juste une instance dont le seul but est d'accrocher la fin de l'exécution des deux méthodes, donc il faut se moquer d'un doNothing. Peut-être que dans votre scénario cela peut être réalisé différemment.

EDIT: Je vais maintenant mieux expliquer ma réponse: dans l'exemple que j'ai partagé, il n'y a que des mocks, donc le test est inutile. Dans le code, où j'ai ajouté !!HERE!!, il devrait y avoir l'appel à la méthode réelle qui appelle réellement les deux méthodes simulées en parallèle. Alternativement, les deux instances de Answer doivent être implémentées pour s'exécuter en parallèle, mais un test avec seulement des mocks n'est pas utile. Étant donné que l'inOrder configuré comme dans mon exemple, vérifie que la seconde invocation a lieu avant la fin de le premier (regardez les commentaires que j'ai ajoutés).

Plus d'informations sur l'interface afinde: http://site.mockito.org/mockito/docs/current/org/mockito/InOrder.html http://www.tutorialspoint.com/mockito/mockito_ordered_verification.htm

+0

Merci. Je ne comprends pas comment cela valide que methodOne et methodTwo s'exécutent en parallèle. Pouvez-vous expliquer cela? –

+0

Je vais modifier ma réponse pour expliquer que –

+0

Désolé pour le retard, edit done! –