Hello and welcome to yet another blog post. In this article, we are going to take a look at the difference between the two annotations i.e. @SpringBootTest and @WebMVCTest. When developing a Spring Boot application, you may have come across two annotations that are commonly used for testing - @SpringBootTest and @WebMvcTest. Both of these annotations provide ways to test your application, but they differ in their scope and purpose. In the past, I have shared difference between @WebMVCTest and @DataJpaTest and in this article, I Am going to explain the difference between @SpringBootTest and @WebMvcTest in Spring Boot. It's also one of the common Spring Boot testing question and I have also included in my list of popular Spring Boot Testing Questions Earlier, Anyway, before seeing the difference between these two, Let's first look at a quick overview of the @SpringBootTest and @WebMvcTest annotations before figuring out how they differ from one another.
What is @SpringBootTest Annotation? What does it do?
@SpringBootTest annotation will make Spring Framework scan your application's all three layers such as the Web layer, Service layer, and Data layer. The root package is where Spring Framework will automatically begin examining your application classes. Beans will be created from classes with annotations like @Component, @Repository, @Service, and @Controller, and added to the application context.The whole application environment will be bootstrapped by @SpringBootTest, allowing us to @Autowire every bean that is discovered during component scanning into our test.
It then enables @Test methods to conduct integration testing after starting the embedded server and creating a web environment.
@SpringBootTest is a more general annotation that loads the entire application context and provides a way to test the application as a whole. It can be used to test the behavior of the application from the top-level perspective, including all the beans, configuration, and auto-configuration that the application has loaded.
What is @WebMVCTest Annotation? What does it do?
@WebMvcTest is a more specific annotation that loads only the web layer of the application. It is primarily used for testing the controller layer of your application, including the request mappings, JSON serialization and deserialization, and other web-related components.The @WebMvcTest annotation will cause Spring Framework to only scan the @Controller, @ControllerAdvice, @JsonComponent, WebMvcConfigurer, and HandlerMethodArgumentResolver classes, which are linked to MVC infrastructure. Classes containing the @Component, @Service, or @Repository annotation will get skipped.
As mentioned earlier, annotation @WebMvcTest is used to test only the Web Layer of your application.
Additionally, you can select which Controllers to scan using the @WebMvcTest annotation. Spring Framework will only scan the designated Controllers in this scenario.
@WebMvcTest(controllers = YourController.class)
class YourControllerTest {
// Class code goes here
}
Difference between @SpringBootTest vs @WebMvcTest in Spring Boot?
The degree of integration testing offered by these two annotations is one of their main differences. The complete application context, which includes the database, security, and other infrastructure components, is loaded by @SpringBootTest. Because of this, it is better suited for integration testing, in which you want to check how your application's many levels interact with one another.However, @WebMvcTest is better suited for unit testing the controller layer because it just loads the web layer and mocks out the other levels. By doing this, you can test the behavior of the controller without having to deal with the intricacy of the other levels.
Another difference between these two annotations is the amount of configuration required. @SpringBootTest requires more configuration because it loads the entire application context. This means you may need to provide additional configuration for testing, such as configuring the database and security components.
On the other hand, @WebMvcTest requires less configuration because it only loads the web layer. This means you don't need to provide additional configuration for other layers of your application, which makes it easier to write and maintain tests.
Example Demonstration
Consider an application that has a RESTful API that allows users to perform CRUD operations on a database. Let's say you want to test the behavior of the entire application, including the web layer, service layer, and database layer. In this scenario, you would use @SpringBootTest.Here's an example:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyApplicationTests {
@Autowired
private MyService myService;
@Autowired
private MyRepository myRepository;
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.build();
}
@Test
public void testCreateUser() throws Exception {
MyEntity user = new MyEntity();
user.setName("John");
user.setAge(30);
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content(asJsonString(user)))
.andExpect(status().isOk());
MyEntity savedUser = myRepository.findById(1L).get();
assertEquals("John", savedUser.getName());
assertEquals(30, savedUser.getAge());
}
}
In this example, we're using @SpringBootTest to load the entire application context and test the behavior of the web layer, service layer, and database layer. We're also using MockMvc to simulate HTTP requests to our RESTful API and test the behavior of the web layer.
Notice how we're autowiring MyService and MyRepository to test the behavior of the service and database layer, respectively. Now let's consider a scenario where you want to test only the web layer of your application, specifically the controller layer. In this case, you would use @WebMvcTest. Here's an example:
@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
public class MyControllerTests {
@Autowired
private MockMvc mockMvc;
@MockBean
private MyService myService;
@Test
public void testGetUser() throws Exception {
MyEntity user = new MyEntity();
user.setId(1L);
user.setName("John");
user.setAge(30);
when(myService.getUser(1L)).thenReturn(user);
mockMvc.perform(get("/api/users/1")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", is("John")))
.andExpect(jsonPath("$.age", is(30)));
}
}
The key difference between these two examples is that the first example uses @SpringBootTest to test the behavior of the entire application, including the service layer and repository layer, while the second example uses @WebMvcTest to test only the behavior of the controller layer, mocking out the service layer. I hope this detailed explanation helps clarify the difference between @SpringBootTest and `@WebMVCTest.
Conclusion
No comments:
Post a Comment