Ich bin neu in Spring Boot und versuche zu verstehen, wie das Testen in SpringBoot funktioniert. Ich bin etwas verwirrt darüber, was der Unterschied zwischen den folgenden beiden Codefragmenten ist:
Code-Snippet 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!")));
}
}
Dieser Test verwendet die @WebMvcTest
Annotation, die meiner Meinung nach für Feature-Slice-Tests gedacht ist, und testet nur die MVC-Schicht einer Webanwendung.
Code-Snippet 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!")));
}
}
Dieser Test verwendet die @SpringBootTest
Anmerkung und a MockMvc
. Wie unterscheidet sich das von Code-Snippet 1? Was macht das anders?
Bearbeiten: Hinzufügen von Code-Snippet 3 (Dies wurde als Beispiel für Integrationstests in der Spring-Dokumentation gefunden.)
@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!"));
}
}
quelle
SpringBootTest
lädt Ihre vollständige App (bis zu einem gewissen Grad wird der eingebettete Container standardmäßig nicht gestartet, wenn einer verfügbar ist, dafürwebEnvironment
ist der da). Ich würde nicht sagen, dass dies@SpringBootTest
ein Komponententest des Controllers ist, sondern eher ein Integrationstest.WebMvcTest
ist wirklich ein Komponententest Ihres Controllers in dem Sinne, dass Sie ihn selbst bereitstellen müssen, wenn er abhängig ist (entweder eine Konfiguration oder eine Art Mock).SpringBootTest
undWebMvcTest
schaffen sind sehr unterschiedlich. Ersteres lädt Ihre GANZE App und aktiviert ALLE automatischen Konfigurationen, während letzteres nur Spring Mvc aktiviert und nur scanntHelloController
. Es kommt doch darauf an, was Sie unter einem Unit-Test verstehen. Aber das ist der Unterschied.Die Annotation @SpringBootTest weist Spring Boot an, nach einer Hauptkonfigurationsklasse zu suchen (z. B. mit @SpringBootApplication) und damit einen Spring-Anwendungskontext zu starten. SpringBootTest lädt die vollständige Anwendung und injiziert alle Bohnen, die langsam sein können.
@WebMvcTest - Zum Testen der Controller-Schicht müssen Sie die verbleibenden Abhängigkeiten angeben, die mit Mock Objects erforderlich sind.
Einige weitere Anmerkungen als Referenz.
Testen von Slices der Anwendung Manchmal möchten Sie ein einfaches „Slice“ der Anwendung testen, anstatt die gesamte Anwendung automatisch zu konfigurieren. Spring Boot 1.4 führt 4 neue Testanmerkungen ein:
Weitere Informationen finden Sie unter: https://spring.io/guides/gs/testing-web/
quelle
MVC-Tests sollen nur den Controller-Teil Ihrer Anwendung abdecken. HTTP-Anforderungen und -Antworten werden verspottet, sodass keine echten Verbindungen hergestellt werden. Wenn Sie dagegen verwenden
@SpringBootTest
, wird die gesamte Konfiguration für den Webanwendungskontext geladen und die Verbindungen werden über den realen Webserver ausgeführt. In diesem Fall verwenden Sie nicht dieMockMvc
Bean, sondern einen StandardRestTemplate
(oder die neue AlternativeTestRestTemplate
).Also, wann sollten wir den einen oder anderen wählen?
@WebMvcTest
soll den Controller von der Serverseite aus einheitlich testen.@SpringBootTest
Andererseits sollte es für Integrationstests verwendet werden, wenn Sie von der Clientseite aus mit der Anwendung interagieren möchten.Das bedeutet nicht, dass Sie keine Mocks verwenden können
@SpringBootTest
. Wenn Sie einen Integrationstest schreiben, kann dies dennoch erforderlich sein. In jedem Fall ist es besser, es nicht nur für den Unit-Test eines einfachen Controllers zu verwenden.Quelle - Lernen von Microservices mit Spring Boot
quelle
@SpringBootTest
, wird ein echter Webserver erst gestartet, wenn Sie auchwebEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
(oder aDEFINED_PORT
) haben und Verbindungen nicht über den echten Webserver hergestellt werden. Der Standardwert für@SpringBootTest
istWebEnvironment.MOCK
.