In this article, I want to share what I learned about testing a Spring application without loading it completely. This can be done by using @DataJpaTest, @WebMvcTest, @SpringBootTest, @AutoConfigureMockMvc and @DataJpaTest. These annotations are part of “test slices” of Spring which allow to test certain beans of the application without loading other beans.
Setup
My simple example application (available on Github) has a PersonController …
… which uses a PersonService …
… and its implementation PersonServiceImpl …
… which uses the PersonRepository:
There are five test classes, each demonstrating one of the test slices.
@SpringBootTest
Test classes annotated with this annotation will load the whole application context and also start a webserver , provided it’s a web MVC application. This is a simple test class using @SpringBootTest:
On my machine, the Spring application context needed 6.9 seconds to load.
@AutoConfigureMockMvc
Only using @SpringBootTest will start a webserver. Adding @AutoConfigureMockMvc to the test class will prevent Spring from starting the server. However, a TestDispatcherServlet is being created which brings the startup time of the test to 7.5 seconds.
@WebMvcTest
If only the web layer of the application should be tested, without starting any web server or even the persistence layer, @WebMvcTest can be used. In this example, the specific controller that should be tested is provided in the annotation, which speeds up start time:
On my machine, the setup of this test needed 3.7 seconds.
It’s noteworthy that only the web layer and specifically only the given controller is set up automatically. Dependencies in the controller will have to be provided in the test class, for example with @MockBean.
@DataJPATest
Kind of the opposite of @WebMvcTest is @DataJpaTest. This annotation only loads the persistence layer:
On my machine, the setup needed 4.9 seconds.
Summary
There are several build-in test layers in Spring that dramatically speed up integration tests.