Difference between using MockMvc with SpringBootTest and Using WebMvcTest
I am new to Spring Boot and am trying to understand how testing works in SpringBoot. I am a bit confused about what is the difference between the following two code snippets:
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!")));
}
}
This test uses the @WebMvcTest
annotation which I believe is for feature slice testing and only tests the MVC layer of a web application.
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!")));
}
}
This test uses the @SpringBootTest
annotation and a MockMvc
. So how is this different from code snippet 1? What does this do differently?
Edit: Adding Code Snippet 3 (Found this as an example of integration testing in the Spring documentation)
@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!"));
}
}
@SpringBootTest
is the general test annotation. If you're looking for something that does the same thing prior to 1.4, that's the one you should use. It does not use slicing at all which means it'll start your full application context and not customize component scanning at all.
@WebMvcTest
is only going to scan the controller you've defined and the MVC infrastructure. That's it. So if your controller has some dependency to other beans from your service layer, the test won't start until you either load that config yourself or provide a mock for it. This is much faster as we only load a tiny portion of your app. This annotation uses slicing.
Reading the doc should probably help you as well.
@SpringBootTest annotation tells Spring Boot to go and look for a main configuration class (one with @SpringBootApplication for instance), and use that to start a Spring application context. SpringBootTest loads complete application and injects all the beans which can be slow.
@WebMvcTest - for testing the controller layer and you need to provide remaining dependencies required using Mock Objects.
Few more annotations below for your reference.
Testing slices of the application Sometimes you would like to test a simple “slice” of the application instead of auto-configuring the whole application. Spring Boot 1.4 introduces 4 new test annotations:
@WebMvcTest - for testing the controller layer
@JsonTest - for testing the JSON marshalling and unmarshalling
@DataJpaTest - for testing the repository layer
@RestClientTests - for testing REST clients
Refer for more information : https://spring.io/guides/gs/testing-web/