There are several ways I recently discovered that increase speed on Spring Boot + JUnit tests substantially. From 8 minutes to 3 minutes.
Some of these are
- Use Right Test Slice (Saved 25% running time)
- Speeding up @SpringBootTest and avoiding @DirtiesContext (Saved 25% running time)
- Run tests in parallel (Saved 37% running time)
Use Right Test Slice (Saved 25% running time)
Several runners come with Spring Boot.
@SpringBootTest is the most general of them. Primarily this is used in combination with
@DirtiesContent, which will restart spring boot after every test class by default which isn’t ideal.
@SpringBootTest is Integration Tests. We don’t want every test to use this.
We want to load the minimum spring-boot infrastructure as possible and still ensure accurate tests. There are a few things that can help:
- If tests are related to a DB. Use
@DataMongoTestor equivalent JPA runner with
- If tests are related to Web/Controller. Use
@WebFluxTestor equivalent Spring MVC runner. If you want to use embedded MongoDB with it, use
@AutoConfigureDataMongo. Most other systems also have annotations starting with
Important: If tests require initializing a single bean. Use
@Importto specify the bean to initialize.
- The best case: Aim for Tests that are purely java based and do not involve spring boot, but it isn’t possible in every scenario.
Speeding up @SpringBootTest and avoiding @DirtiesContext (Saved 25% running time)
@DirtiesContext is an annotation that recreated the Spring Context after each test or each test class. To avoid using
@DirtiesContext, ensure all your tests don’t depend on the same data. For this, you can wrap your data creation in a test data factory and ensure the data produced is random.
As previously mentioned, one should avoid using
@SpringBootTest, but if you can’t do without it, ensure you use
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
Try to use it with
@ContextConfiguration to limit the creation of beans.
Run tests in parallel (Saved 37% running time)
junit-platform.properties file in
test/resource/junit-platform.properties and add the following minimum. 1
junit.jupiter.execution.parallel.enabled = true
Now you can either use one of these,
- add the following to every class you want to run parallel.
- add more to
junit.jupiter.execution.parallel.mode.default = same_thread|concurrent junit.jupiter.execution.parallel.mode.classes.default = same_thread|concurrent
Some tests can’t run parallelly, so I prefer manually adding
I found data tests with
@DataMongoTest by asserting over different data.
Another positive side effect of having
@Execution(CONCURRENT) is that these tests run first. And since these tests are faster than the SAME_THREAD mode, they lead to instant feedback.
What are some other ways to speed up JUnit performance?