2016-07-13 23 views
0

Ich erstelle einen Komponententest, um zu zeigen, dass zwei Methoden parallel ausgeführt werden. Dazu verspotte ich die beiden Methoden und habe beide eine Verzögerung von 2 Sekunden. Ich bestätige dann, dass der Komponententest weniger als 4 genommen hat (so kann ich sicher sein, dass die Aktionen nicht sequentiell ausgeführt werden, da dies mehr als 4 [2 * 2] Sekunden dauern würde).Validierungsmethoden werden parallel ausgeführt

Gibt es einen besseren Weg?

+1

Log Anfang und Ende in der Mock. Beide sollten vor jedem Ende beginnen, und Sie können die Protokolleinträge verwenden, um dies zu überprüfen (oder eine gemeinsam genutzte Variable zu erhöhen - atomar! - Wenn die Aufgabe beginnt, dekrementieren, wenn sie endet, verfolgen Sie ihre max, und überprüfen Sie die Antwort ist zwei) . Usw. –

+0

Sind die beiden Methoden aus dem gleichen Mock? –

+0

@LorenzoMurrocu wir möchten beide Situationen unterstützen. Gleiches Schein und anderes. –

Antwort

1

Ich würde die InOrder-Funktion verwenden. Dies ist ein Beispiel für den Fall, dass die beiden Methoden aus dem gleichen mock sind:

@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. 
} 

In diesem Beispiel ist mock3 nur ein Beispiel:

@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. 
} 

Sie die inOrder auch mit mehreren Mocks verwenden können dessen einziger Zweck es ist, das Ende der Ausführung der beiden Methoden zu haken, so sollte es mit einem doNothing verspottet werden. Vielleicht kann dies in Ihrem Szenario anders erreicht werden.

EDIT: Ich werde jetzt besser meine Antwort erklären: in dem Beispiel, das ich geteilt habe, gibt es nur Mocks, so dass der Test nutzlos ist. In dem Code, in dem ich !!HERE!! hinzugefügt habe, sollte der Aufruf der Real-Methode sein, die die beiden mocked-Methoden tatsächlich parallel aufruft. Alternativ sollten die beiden Instanzen von Answer parallel ausgeführt werden, aber ein Test mit nur Mocks ist nicht sinnvoll. Vorausgesetzt, dass die in meinem Beispiel konfigurierte inOrder überprüft, dass der zweite Aufruf vor dem Ende von erfolgt der erste (sieh dir die Kommentare an, die ich hinzugefügt habe).

Mehr Informationen über inOrder Schnittstelle: http://site.mockito.org/mockito/docs/current/org/mockito/InOrder.html http://www.tutorialspoint.com/mockito/mockito_ordered_verification.htm

+0

Danke. Ich verstehe nicht, wie dies bestätigt, dass methodOne und methodTwo parallel ausgeführt werden. Kannst du das erklären? –

+0

Ich werde meine Antwort zu erklären, dass –

+0

Entschuldigung für die Verzögerung bearbeiten getan! –