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?
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/
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With