Mockito überprüft die Reihenfolge / Reihenfolge der Methodenaufrufe

205

Gibt es eine Möglichkeit zu überprüfen, ob in Mockito methodOnezuvor a aufgerufen methodTwowurde?

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
quelle

Antworten:

305

InOrder hilft dir dabei.

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
quelle
5
Dies ist korrekt, obwohl die Aufrufe von doNothing hier nur als Platzhalter für andere Stubbing benötigt werden. Mockito akzeptiert standardmäßig stille Methodenaufrufe.
Jeff Bowman
1
Es akzeptiert sie, während das Objekt keine Abhängigkeiten hat, wenn das Objekt Abhängigkeiten hat, gibt es eine Ausnahme =)
Koitoer
14
Berücksichtigen Sie inOrder.verifyNoMoreInteractions();nach der letzten Überprüfung in diesem Beispiel, ob keine anderen Anrufe getätigt wurden.
DwB
1
Nur zur Verdeutlichung: Es ist sicher, inOrder kurz vor der Überprüfung zu definieren - nachdem einige (getestete) Methoden für Mocks aufgerufen wurden.
user3078523
Sind die Ergebnisse für inOrder(firstMock, secondMock)und gleich inOrder(secondMock, firstMock)? Vielleicht können Sie die Antwort aktualisieren, um dies zu notieren.
Kevinarpe
94

Beachten Sie, dass Sie auch die InOrder- Klasse verwenden können, um zu überprüfen, ob verschiedene Methoden in der Reihenfolge für einen einzelnen Mock aufgerufen werden, nicht nur für zwei oder mehr Mocks.

Angenommen, ich habe zwei Klassen Foound Bar:

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

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

Ich kann dann eine Testklasse Test hinzufügen , dass Bar‚s firstThenSecond()Methode tatsächlich aufruft first(), dann second(), und nicht second(), dann first(). Siehe folgenden Testcode:

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
quelle
1
Dies sollte ein Kommentar zur akzeptierten Antwort sein, keine ganz neue Antwort.
Ach
12
Ich bin mit Ihrem Kommentar @ach nicht einverstanden. Das Codebeispiel hilft, daher ist eine neue Antwort sinnvoll.
Snekse
2
Gibt es eine Möglichkeit zu überprüfen, ob dieselbe Methode zweimal aufgerufen wird, aber die Reihenfolge der übergebenen Parameter überprüft wird? zB Erst find('foo')dannfind('bar')
Snekse
1
Sieht so aus, als wäre dies meine Antwort stackoverflow.com/questions/36573399/…
Snekse
3
Dies ist tatsächlich ein besseres Beispiel als die akzeptierte Antwort, da es eine typischere Verwendung zeigt alsdoNothing()
Archimedes Trajano
37

Ja, dies ist in der Dokumentation beschrieben. Sie müssen die InOrder- Klasse verwenden.

Beispiel (unter der Annahme, dass bereits zwei Mocks erstellt wurden):

InOrder inOrder = inOrder(serviceAMock, serviceBMock);

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

Mit BDD ist es

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


}
Thraker
quelle