2012-05-29 8 views
68

Pisząc nowy test jUnit4, zastanawiam się, czy użyć @RunWith (MockitoJUnitRunner.class) lub MockitoAnnotations.initMocks (this).@RunWith (MockitoJUnitRunner.class) vs MockitoAnnotations.initMocks (this)

Utworzono nowy test & kreator automatycznie wygenerował test z Runner. Javadocs do stanu MockitoJUnitRunner następujące:

Kompatybilny z JUnit 4.4 i wyższej, to biegacz dodaje następujące zachowania:

inicjuje drwi opatrzone Mock, tak, że jawne użycie MockitoAnnotations.initMocks (obiektu) nie jest konieczne . Mocks są inicjowane przed każdą metodą testową. sprawdza poprawność użycia ramki po każdej metodzie testu.

To nie jest dla mnie jasne, czy za pomocą Runner ma żadnej przewagi nad initMocks() metoda używam w przeszłości.

Wszelkie myśli lub linki będą mile widziane!

Odpowiedz

85

MockitoJUnitRunner umożliwia automatyczną weryfikację użycia szkieletu, a także automatyczną aktualizację initMocks().

Automatyczne sprawdzanie poprawności użycia frameworku jest rzeczywiście warte. Daje ci to lepsze raportowanie, jeśli popełnisz jeden z tych błędów.

  • zadzwonić statycznej when metodę, ale nie zakończyć stubbing z pasującym thenReturn, thenThrow lub then. (Error 1 w poniższym kodzie)

  • zadzwonić verify na pozornie, ale zapomnij podać wywołanie metody który próbujesz zweryfikować. (Error 2 w poniższym kodzie)

  • wywołać metodę when po doReturn, doThrow lub doAnswer i zdać makiety, ale zapomnij podać metodę próbujesz skrótową. (Error 3 w poniższym kodzie)

Jeśli nie masz walidacji użytkowania ramowej, te błędy są nie podano do następującym wywołaniu metody Mockito.Może to być

  • w taki sam sposób jak badania (błąd 1 poniżej)
  • w następnej metody testowej (np błędu 2 poniżej)
  • w następnej grupy testowej.

Jeśli pojawią się w ostatnim przeprowadzonym teście (jak w przypadku błędu 3 poniżej), nie zostaną one w ogóle zgłoszone.

Oto, jak może wyglądać każdy z tych typów błędów. Załóżmy, że JUnit uruchamia te testy w kolejności, w jakiej są tutaj wymienione.

@Test 
public void test1() { 

    // ERROR 1 
    // This compiles and runs, but it's an invalid use of the framework because 
    // Mockito is still waiting to find out what it should do when myMethod is called. 
    // But Mockito can't report it yet, because the call to thenReturn might 
    // be yet to happen. 
    when(myMock.method1()); 

    doSomeTestingStuff(); 

    // ERROR 1 is reported on the following line, even though it's not the line with 
    // the error. 
    verify(myMock).method2(); 

} 

@Test 
public void test2() { 

    doSomeTestingStuff(); 

    // ERROR 2 
    // This compiles and runs, but it's an invalid use of the framework because 
    // Mockito doesn't know what method call to verify. But Mockito can't report 
    // it yet, because the call to the method that's being verified might 
    // be yet to happen. 
    verify(myMock); 
} 

@Test 
public void test3() { 

    // ERROR 2 is reported on the following line, even though it's not even in 
    // the same test as the error. 
    doReturn("Hello").when(myMock).method1(); 


    // ERROR 3 
    // This compiles and runs, but it's an invalid use of the framework because 
    // Mockito doesn't know what method call is being stubbed. But Mockito can't 
    // report it yet, because the call to the method that's being stubbed might 
    // be yet to happen. 

    doReturn("World").when(myMock); 

    doSomeTestingStuff(); 

    // ERROR 3 is never reported, because there are no more Mockito calls. 
} 

Teraz, kiedy pierwszy raz napisał tę odpowiedź więcej niż pięć lat temu, pisałem

Więc polecam korzystanie z MockitoJUnitRunner jeśli możliwe. Jednak, jak słusznie zauważył Tomasz Nurkiewicz, nie możesz go użyć, jeśli potrzebujesz kolejnego biegacza JUnit, takiego jak Spring.

Moja rekomendacja się zmieniła. Zespół Mockito dodał nową funkcję, odkąd po raz pierwszy napisałem tę odpowiedź. Jest to reguła JUnit, która wykonuje dokładnie tę samą funkcję, co MockitoJUnitRunner. Ale jest lepiej, ponieważ nie wyklucza użycia innych biegaczy.

Dołącz

@Rule 
public MockitoRule rule = MockitoJUnit.rule(); 

w swojej klasie testowej. To inicjuje makiety i automatyzuje sprawdzanie poprawności struktury; tak jak robi to MockitoJUnitRunner. Ale teraz możesz użyć SpringJUnit4ClassRunner lub dowolnego innego JUnitRunnera. Od wersji Mockito 2.1.0 są dodatkowe opcje, które kontrolują dokładnie, jakie problemy zgłaszane są.

+3

Zobacz [javadocs dla 'Mockito.validateMockitoUsage()'] (http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#validateMockitoUsage%28%29), aby uzyskać więcej informacji na ten temat uprawomocnienie. – avandeursen

+0

Zdecydowanie nie mogę powiedzieć, że są takie same. w jednym przypadku testowym konfiguracja junit runner zawodzi dla mnie i nie wstrzykuje poprawnie moich prób, chyba że zrobię initMocks setup – dtc

+0

Używamy testng 6.8.8 + mockito 1.10.19 i, oczywiście, nie możemy użyć MockitoJUnitRunner, ale ramy walidacji nadal działają! I działa dokładnie tak, jak @David Wallace. Czy ktoś może wyjaśnić? Czy to dlatego, że wciąż mamy wywołania zwrotne @ Before * i MockitoAnnotations.initMocks (this)? – yuranos87

23

Użycie Runner pozwala zaoszczędzić trochę kodu (nie ma potrzeby stosowania metody @Before). Z drugiej strony używanie runnera czasami nie jest możliwe, tj. Gdy już go używasz, na przykład SpringJUnit4ClassRunner.

To wszystko. To tylko kwestia preferencji.

+1

Oprócz metody initMocks(), metoda @Before będzie nadal potrzebna dla każdej innej konfiguracji, prawda? – OceanBlue

+1

@OceanBlue: Oczywiście, jeśli twoja metoda '@ Before' zawierała coś innego niż' initMocks() 'niż musisz zachować to po migracji do runnera. –

+0

Odpowiedź Davida Wallace'a na temat walidacji frameworku w pełni odpowiada na moje pytanie, więc zaakceptowałem to, ale +1 za to, że ten biegacz nie może być użyty z innym, jak na przykład wiosenny. Dzięki! – OceanBlue