Jak używać Mockito z JUnit5

109

Jak mogę używać zastrzyku z Mockito i JUnit 5?

W JUnit4 mogę po prostu użyć @RunWith(MockitoJUnitRunner.class)Adnotacji. W JUnit5 nie ma @RunWithadnotacji?

Daniel Käfer
źródło

Odpowiedzi:

153

Istnieją różne sposoby korzystania z Mockito - omówię je jeden po drugim.

Ręcznie

Ręczne tworzenie mocków z Mockito::mockdziałaniami niezależnie od wersji JUnit (lub frameworka testowego).

Oparte na adnotacjach

Korzystanie z @Mock -annotation i odpowiednie wywołanie MockitoAnnotations::initMocks do tworzenia mocks działa niezależnie od wersji JUnit (lub ram testu dla tej sprawy, ale Java 9 mogłyby kolidować tutaj, w zależności od tego, czy kod testowy kończy się w module, czy nie).

Rozszerzenie Mockito

JUnit 5 ma potężny model rozszerzeń, a Mockito niedawno opublikował jeden z identyfikatorem grupy / artefaktu org.mockito : mockito-junit-jupiter .

Możesz zastosować rozszerzenie, dodając @ExtendWith(MockitoExtension.class)do klasy testowej i dodając adnotacje do mockowanych pól za pomocą @Mock. Z MockitoExtensionJavaDoc:

@ExtendWith(MockitoExtension.class)
public class ExampleTest {

    @Mock
    private List list;

    @Test
    public void shouldDoSomething() {
        list.add(100);
    }

}

Dokumentacja MockitoExtension opisuje inne sposoby tworzenia instancji mocków, na przykład za pomocą iniekcji konstruktora (jeśli określasz końcowe pola w klasach testowych).

Bez zasad, bez biegaczy

Reguły JUnit 4 i biegacze nie działają w JUnit 5, więc nie można używać MockitoRulei Mockito runner .

Nicolai Parlog
źródło
6
Istnieje teraz oficjalne rozszerzenie Mockito Junit5, które jest odpowiednikiem MockitoJUnitRunner -> mockito-junit-jupiter
dan carter
Kiedy oficjalne rozszerzenie do Mockito zostało wydane, napisał post na blogu ze szczegółami, jak go skonfigurować i używać: solidsoft.wordpress.com/2018/03/27/…
Marcin Zajączkowski
Czy metoda z adnotacją @Testmusi być publiczna czy „prywatny pakiet” jest wystarczająco dobra?
Geek
Podczas uruchamiania testów z Jowiszem (często nazywanym „JUnit 5”), metody testowe muszą być widoczne tylko w pakiecie.
Nicolai Parlog
61

Użyj Mockito's MockitoExtension. Rozszerzenie jest zawarte w nowym artefakcie mockito-junit-jupiter:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>2.23.4</version>
    <scope>test</scope>
</dependency>

Pozwala na pisanie testów tak, jak w przypadku JUnit 4:

import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;

@ExtendWith(MockitoExtension.class)
class MyTest {

    @Mock
    private Foo foo;

    @InjectMocks
    private Bar bar; // constructor injection

    ...
}
Jonathan
źródło
7
@ExtendWith(MockitoExtension.class)jest odpowiednikiem @RunWith(MockitoJUnitRunner.class)JUnit4
Sergey Nemchinov
Czy mogę wykonać wiele wywołań metody z różnymi wartościami zwracanymi w metodzie obiektu Mock przy użyciu MockitoExtension.class w JUnit5
Raj Hassani
@RajHassani Tak, możesz zobaczyć tutaj .
Jonathan
10

org.junit.jupiter.api.extension.ExtensionMożna to zrobić na różne sposoby, ale bardziej przejrzysty i zgodny z filozofią JUnit 5 polega na stworzeniu Mockito.

1) Ręczne tworzenie mocków powoduje utratę korzyści z dodatkowych kontroli Mockito, aby upewnić się, że poprawnie używasz frameworka.

2) Wywołanie MockitoAnnotations.initMocks(this)w każdej klasie testowej jest kodem płyty kotłowej, którego możemy uniknąć.
Tworzenie tej konfiguracji w klasie abstrakcyjnej również nie jest dobrym rozwiązaniem.
Łączy wszystkie klasy testowe z klasą bazową.
Jeśli z ważnych powodów potrzebujesz nowej podstawowej klasy testowej, kończysz z 3-poziomową hierarchią klas. Proszę tego unikać.

3) Reguły testowe to specyfika JUnit 4.
Nawet o tym nie myśl.
A dokumentacja jest jasne, że:

Jeśli jednak zamierzasz opracować nowe rozszerzenie dla JUnit 5, użyj nowego modelu rozszerzenia JUnit Jupiter zamiast modelu opartego na regułach JUnit 4.

4) Test Runner naprawdę nie jest sposobem na rozszerzenie frameworka JUnit 5.
JUnit 5 uprościł piekło Runners of JUnit 4, udostępniając model rozszerzenia do pisania testów dzięki JUnit 5 Extensions.
Nawet o tym nie myśl.

Więc sprzyjaj org.junit.jupiter.api.extension.Extensiondrodze.


EDYCJA: Właściwie Mockito zawiera rozszerzenie Jowisza: mockito-junit-jupiter

Następnie bardzo prosty w użyciu:

import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class FooTest {
     ...    
}

Oto dodatek do doskonałej odpowiedzi Jonathana.

Dodając jako zależność mockito-junit-jupiterartefakt, podczas @ExtendWith(MockitoExtension.class)wykonywania testu zostanie użyty następujący wyjątek:

java.lang.NoSuchMethodError: org.junit.platform.commons.support.AnnotationSupport.findAnnotation (Ljava / util / Optional; Ljava / lang / Class;) Ljava / util / Optional;

Problem polega na tym, że mockito-junit-jupiterzależy to od dwóch niezależnych bibliotek. Na przykład dla mockito-junit-jupiter:2.19.0:

<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>2.19.0</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-api</artifactId>
  <version>5.1.0</version>
  <scope>runtime</scope>
</dependency>

Problem był używany junit-jupiter-api:5.0.1.

Ponieważ junit-jupiter-apiruchy wciąż są częste w zakresie API, upewnij się, że polegasz na tej samej wersji, od junit-jupiter-apiktórej mockito-junit-jupiterzależy.

davidxxx
źródło
dlaczego nie mockito-junit-jupiterściągnie właściwej wersji junit-jupiter-api?
haelix
@haelix Ponieważ strategia wersji używana dla tej zależności opiera się na bibliotece Mockito. Spójrz na wersję tutaj mockito-junit-jupiter:2.19.0. Chociaż wersje JUnit Jupiter zaczynają się od 5. mockito-junit-jupiter powinien był określić w swoim identyfikatorze artefaktu dwie rzeczy (wersja Mockito i wersja JUnit Jupiter), aby wszystko było jaśniejsze. Na przykład, mockito-junit-jupiter-5.1:2.19.0aby przekazać, że biblioteka jest zaprojektowana dla JUnit Jupiter 5.1.
davidxxx
MockitoExtensionnie wydaje się istnieć w mockito-corewersji 3.0.0.
Thunderforge
1
@Thunderforge To jest zdefiniowane wmockito-junit-jupiter
davidxxx
3

Musisz użyć nowej @ExtendWithadnotacji.

Niestety nie ma jeszcze żadnego rozszerzenia. Na github możesz zobaczyć wersję beta rozszerzenia. jako przykład test demo .

Daniel Käfer
źródło