Jestem nowy w Spring Boot i próbuję zrozumieć, jak działa testowanie w SpringBoot. Nie wiem, jaka jest różnica między następującymi dwoma fragmentami kodu:
Fragment kodu 1:
@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class HelloControllerApplicationTest {
@Autowired
private MockMvc mvc;
@Test
public void getHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Greetings from Spring Boot!")));
}
}
Ten test wykorzystuje @WebMvcTest
adnotację, która moim zdaniem służy do testowania wycinka funkcji i testuje tylko warstwę MVC aplikacji internetowej.
Fragment kodu 2:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {
@Autowired
private MockMvc mvc;
@Test
public void getHello() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Greetings from Spring Boot!")));
}
}
Ten test używa @SpringBootTest
adnotacji i pliku MockMvc
. Czym różni się to od fragmentu kodu 1? Co to robi inaczej?
Edycja: dodawanie fragmentu kodu 3 (znaleziono to jako przykład testowania integracji w dokumentacji Spring)
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerIT {
@LocalServerPort private int port;
private URL base;
@Autowired private TestRestTemplate template;
@Before public void setUp() throws Exception {
this.base = new URL("http://localhost:" + port + "/");
}
@Test public void getHello() throws Exception {
ResponseEntity < String > response = template.getForEntity(base.toString(), String.class);
assertThat(response.getBody(), equalTo("Greetings from Spring Boot!"));
}
}
źródło
SpringBootTest
ładuje twoją pełną aplikację (do pewnego stopnia, domyślnie nie uruchamia osadzonego kontenera, jeśli jest dostępny, do tegowebEnvironment
służy). Nie powiedziałbym, że@SpringBootTest
jest to test jednostkowy kontrolera, ale raczej test integracji, tak naprawdę.WebMvcTest
jest tak naprawdę testem jednostkowym twojego kontrolera w tym sensie, że jeśli ma zależności, będziesz musiał je dostarczyć sam (konfigurację lub jakąś próbę).SpringBootTest
iWebMvcTest
jest bardzo różny. Pierwsza z nich ładuje CAŁĄ aplikację i włącza WSZYSTKIE automatyczne konfiguracje, podczas gdy druga włącza tylko Spring Mvc i nie skanuje niczego pozaHelloController
. W końcu wszystko zależy od tego, co masz na myśli przez test jednostkowy. Ale to jest różnica.Adnotacja @SpringBootTest mówi Spring Boot, aby poszedł i poszukał głównej klasy konfiguracji (na przykład z @SpringBootApplication) i użył jej do uruchomienia kontekstu aplikacji Spring. SpringBootTest ładuje całą aplikację i wstrzykuje wszystkie ziarna, które mogą działać wolno.
@WebMvcTest - do testowania warstwy kontrolera i musisz podać pozostałe zależności wymagane przy użyciu Mock Objects.
Kilka dodatkowych adnotacji poniżej w celach informacyjnych.
Testowanie wycinków aplikacji Czasami chcesz przetestować prosty „wycinek” aplikacji zamiast automatycznej konfiguracji całej aplikacji. Spring Boot 1.4 wprowadza 4 nowe adnotacje testowe:
Więcej informacji: https://spring.io/guides/gs/testing-web/
źródło
Testy MVC mają na celu objęcie tylko kontrolera aplikacji. Żądania i odpowiedzi HTTP są mockowane, więc nie są tworzone rzeczywiste połączenia. Z drugiej strony, kiedy używasz
@SpringBootTest
, cała konfiguracja kontekstu aplikacji internetowej jest ładowana, a połączenia przechodzą przez prawdziwy serwer sieciowy. W takim przypadku nie używaszMockMvc
fasoli, aleRestTemplate
zamiast tego standard (lub nowa alternatywaTestRestTemplate
).Kiedy więc powinniśmy wybrać jedną lub drugą?
@WebMvcTest
ma na celu jednostronne przetestowanie kontrolera po stronie serwera.@SpringBootTest
z drugiej strony powinien być używany do testów integracyjnych, gdy chcemy współdziałać z aplikacją od strony klienta.Nie oznacza to, że nie możesz używać makiet z
@SpringBootTest
; jeśli piszesz test integracji, może to być nadal konieczne. W każdym razie lepiej nie używać go tylko do prostego testu jednostkowego kontrolera.źródło - Learning Microservices with Spring Boot
źródło
@SpringBootTest
, prawdziwy serwer WWW nie jest uruchamiany, chyba że masz równieżwebEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
(lub aDEFINED_PORT
), a połączenia nie przechodzą przez prawdziwy serwer WWW. Wartość domyślna@SpringBootTest
toWebEnvironment.MOCK
.