Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

difference between @SpringBootTest(classes = SomeController.class) and @WebMvcTest(SomeController.class)

I understand that using @SpringbootTest I raise whole spring contex during test, or In my case using @SpringBootTest(classes = SomeController.class) I raise only one bean -> SomeController. If this controller have some dependencies I need to mock them up. Using annotation @WebMvcTest(SoneController.class) I will (based on my knowledge) achieve the same goal.

Question is: Are there any differences between those two annotations used in provided example?

like image 678
true_H Avatar asked Sep 06 '25 03:09

true_H


2 Answers

There's a clear difference between @SpringBootTest(classes = SomeController.class) and @WebMvcTest(SomeController.class).

  • @SpringBootTest(classes = SomeController.class) - starts a server (i.e like Tomcat) + spring application context with the component SomeController.class. In addition to the controller, you should normally specify the context configuration to successfully start the whole app (For ex: when you don't specify the classes, it falls back to @SpringBootApplication).

  • @WebMvcTest(SomeController.class) - only starts the web layer of the application with SomeController.class.

What's the difference?

@SpringBootTest tests are usually integration tests, you start the full spring-boot application and test against that black box. You can still tweak the application startup by providing configuration, properties, web server type etc in the annotation parameters.

But @WebMvcTest(SomeController.class) is usually a unit test for your controller. These are lightweight and fast. The dependencies like @Service classes are mocked in such tests.

This is a good starting point - https://spring.io/guides/gs/testing-web/

like image 107
Laksitha Ranasingha Avatar answered Sep 07 '25 19:09

Laksitha Ranasingha


There are several subtle differences between these two ways.
But you will discover a part of them only randomly when you will encounter problems such as bean initialization exception during the spring boot context init or a NullPointerException rising during the test execution.
To make things simpler, focus on intention.
When you write that :

@SpringBootTest(classes = SomeController.class)

you will make Spring to init only the SomeController bean instance.
Is it desirable to test a controller ?
Probably no since you need a way to invoke the controller with a controller approach.
For that a MockMvc instance would help. With WebMvcTest you get that bean additionally loaded in the test context.
So that way is preferable :

@WebMvcTest(SomeController.class)
public class SomeControllerTest{
    
  @Autowired
  private MockMvc mvc;
...
}

Of course you could get a similar behavior with @SpringBootTest and some additional classes but it will be just an overhead : the @WebMvcTest specialized annotation is enough.

At last why make the reading of the test class harder for your follower ?
By weaving a contrived way of using spring boot test annotation, chances are good to come there.

like image 44
davidxxx Avatar answered Sep 07 '25 20:09

davidxxx