Podczas tworzenia testów i mockowania zależności, jaka jest różnica między tymi trzema podejściami?
@MockBean:
@MockBean MyService myservice;
@Drwić:
@Mock MyService myservice;
Mockito.mock ()
MyService myservice = Mockito.mock(MyService.class);
Zwykła biblioteka Mockito
import org.mockito.Mock;
...
@Mock
MyService myservice;
i
import org.mockito.Mockito;
...
MyService myservice = Mockito.mock(MyService.class);
pochodzą z biblioteki Mockito i są funkcjonalnie równoważne.
Pozwalają na mockowanie klasy lub interfejsu oraz rejestrowanie i weryfikację zachowań na nim.
Sposób korzystania z adnotacji jest krótszy, dlatego jest preferowany i często preferowany.
Należy pamiętać, że aby włączyć adnotacje Mockito podczas wykonywania testów,
MockitoAnnotations.initMocks(this)
należy wywołać metodę statyczną.
Aby uniknąć skutków ubocznych między testami, zaleca się robić to przed każdym wykonaniem testu:
@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
Innym sposobem włączenia adnotacji Mockito jest dodanie adnotacji do klasy testowej @RunWith
poprzez określenie, MockitoJUnitRunner
która wykonuje to zadanie, a także inne przydatne rzeczy:
@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}
Biblioteka Spring Boot opakowująca bibliotekę Mockito
To jest rzeczywiście klasa Spring Boot :
import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;
Klasa jest zawarta w spring-boot-test
bibliotece.
Pozwala na dodanie Mockito na wiosnę ApplicationContext
.
Jeśli bean, zgodny z zadeklarowaną klasą, istnieje w kontekście, zastępuje go makietą.
Jeśli tak nie jest, dodaje makietę w kontekście jako ziarno.
Dokumentacja Javadoc:
Adnotacja, której można użyć do dodania mocków do Spring ApplicationContext.
...
Jeśli jakakolwiek istniejąca pojedyncza fasola tego samego typu zdefiniowana w kontekście zostanie zastąpiona makietą, jeśli żadna istniejąca fasola nie zostanie zdefiniowana, zostanie dodana nowa.
Kiedy używasz klasycznego / zwykłego Mockito i kiedy używasz @MockBean
Spring Boot?
Testy jednostkowe są przeznaczone do testowania komponentu w oderwaniu od innych komponentów, a testy jednostkowe mają również wymóg: być możliwie najszybszym pod względem czasu wykonania, ponieważ testy te mogą być wykonywane każdego dnia kilkadziesiąt razy na maszynach deweloperskich.
W związku z tym oto prosta wskazówka:
Kiedy piszesz test, który nie potrzebuje żadnych zależności z kontenera Spring Boot, klasyczny / prosty Mockito jest drogą do naśladowania: jest szybki i sprzyja izolacji testowanego komponentu.
Jeśli Twój test musi opierać się na kontenerze Spring Boot i chcesz również dodać lub udawać jeden z komponentów bean pojemnika: @MockBean
Spring Boot jest najlepszym rozwiązaniem.
Typowe zastosowanie Spring Boot @MockBean
Podczas pisania klasy testowej z adnotacją @WebMvcTest
(wycinek testu internetowego).
Dokumentacja Spring Boot bardzo dobrze to podsumowuje:
Często
@WebMvcTest
będzie ograniczony do jednego kontrolera i używany w połączeniu z@MockBean
symulowanymi implementacjami dla wymaganych współpracowników.
Oto przykład :
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@RunWith(SpringRunner.class)
@WebMvcTest(FooController.class)
public class FooControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private FooService fooServiceMock;
@Test
public void testExample() throws Exception {
Foo mockedFoo = new Foo("one", "two");
Mockito.when(fooServiceMock.get(1))
.thenReturn(mockedFoo);
mvc.perform(get("foos/1")
.accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().string("one two"));
}
}
@MockBean
spowoduje zastąpienie komponentu bean w kontekście aplikacji, jeśli komponent bean deklarujący ten sam typ jest już zdefiniowany w konfiguracji Spring. I wstrzyknięcie jest wykonywane w klasie, w której deklarujesz@MockBean.
. Mechanizmy DI działają w ten sposób: rejestrujesz obiekt w kontekście DI, a następnie możesz wstrzyknąć obiekt, do którego odwołuje się kontekst Spring, w określonej klasie. Nie wstrzykujesz obiektu w kontekście DI.Na koniec łatwo to wytłumaczyć. Jeśli spojrzysz tylko na javadoc adnotacji, zobaczysz różnice:
@Mock: (
org.mockito.Mock
)@MockBean: (
org.springframework.boot.test.mock.mockito.MockBean
)Mockito.mock ()
źródło
@MockBean
i to,@Mock
że jeden wstrzyknie próbę doSpring ApplicationContext
drugiego, a drugi nie?@MockBean
, musisz dodać adnotację do klasy@RunWith(SpringRunner.class)
. Jednak do używania@Mock
możesz użyć@RunWith(MockitoJUnitRunner.class)
i wywołać initMocks (), jak wspomniał @ Florian-schaetz.@Mock
będzie działać również ze SpringRunner, ale z dodatkowym obciążeniem związanym z ładowaniem aplikacjiKontekst