You're reading for free via Master Spring Ter's Friend Link. Become a member to access the best of Medium.
Member-only story
Speeding Up Your Spring Boot Tests: Practical Tips and Code Examples

When your Spring Boot test suite takes too long, it slows you down. Slow tests discourage frequent runs, break your flow, and can even mask issues that pop up in between test executions. The good news: you can do a lot to shrink that runtime. Let’s look at some strategies and accompany them with a few code examples to make things clearer.
for free reading -> https://erkanyasun.medium.com/speeding-up-your-spring-boot-tests-practical-tips-and-code-examples-8b6adbd129e0?source=friends_link&sk=64c29bcb8b2252d23ca25cb77d943585
1. Trim the Spring Context
The Problem:
A full @SpringBootTest
loads the entire application: controllers, services, security configs, messaging beans—everything. This can be expensive, especially when you only need a sliver of the application for your test.
The Fix:
Use more selective annotations. For instance, if you’re testing a web controller’s JSON response, @WebMvcTest
loads only web components. If you’re testing a JPA repository, @DataJpaTest
focuses on data layers.
Example:
// Instead of:
@SpringBootTest
class MyControllerIntegrationTest {
@Autowired
MockMvc mockMvc;
@Test
void shouldReturnOk() throws Exception {
mockMvc.perform(get("/hello"))
.andExpect(status().isOk());
}
}
// Use this:
@WebMvcTest(MyController.class)
class MyControllerIntegrationTest {
@Autowired
MockMvc mockMvc;
@Test
void shouldReturnOk() throws Exception {
mockMvc.perform(get("/hello"))
.andExpect(status().isOk());
}
}
This approach avoids loading your entire Spring context — like your messaging configs or data layer — just for a controller test.
2. Embrace Test Slices
Why:
Spring’s test slicing annotations — @WebMvcTest
, @DataJpaTest
, @JdbcTest
, @JsonTest
, etc.—load only the beans needed for the slice of functionality you’re testing.
Example:
@DataJpaTest
class UserRepositoryTest {
@Autowired
UserRepository userRepository;
@Test
void findByUsername() {
userRepository.save(new User("alice", "password123"));
User found = userRepository.findByUsername("alice");
assertThat(found).isNotNull();
}
}
@DataJpaTest
brings up a minimal context with an in-memory database and JPA repositories only—super fast startup compared to a full-blown app context.
3. Reuse the Application Context
Why:
Starting the Spring context repeatedly is costly. Spring tries to cache the context between tests if the configuration is the same.
What to Do:
- Standardize your configuration.
- Avoid randomizing ports and configurations unnecessarily.
- Don’t mix too many different configurations across test classes.
Example:
Make sure all your @SpringBootTest
tests use the same configuration by placing shared config in src/test/resources/application-test.yaml
and annotating tests with:
@SpringBootTest(properties = {
"spring.config.location=classpath:/application-test.yaml"
})
This ensures all tests use the same context, letting the Spring Test framework reuse it.
Need help with Spring Framework? Master Spring TER, a ChatGPT model, offers real-time troubleshooting, problem-solving, and up-to-date Spring Boot info. Click master-spring-ter for free expert support!
4. Write Plain Unit Tests Without Spring
Why:
If you’re testing a simple utility or a service with no Spring dependencies, don’t bring up the whole framework. Regular JUnit tests are instantaneous.
Example:
// No @SpringBootTest or any Spring annotation
class PasswordHasherTest {
private final PasswordHasher hasher = new PasswordHasher();
@Test
void shouldHashPassword() {
String hashed = hasher.hash("mySecret");
assertNotNull(hashed);
// assert other properties as needed
}
}
No Spring context means no startup cost — just run the logic and check results.
5. Keep Integration Tests Targeted and Run Them Less Frequently
The Idea:
Integration tests are great for verifying that components work together, but they’re inherently slower. Consider separating your build pipeline steps: run unit tests frequently, and run integration tests less often (e.g., only on commit or in CI).
Example (Maven Setup):
In your pom.xml
:
<profiles>
<profile>
<id>it-tests</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M5</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Then run mvn test
for quick unit tests, and mvn verify -Pit-tests
for slower integration tests.
6. Parallel Test Execution
Why:
If you have multiple CPU cores, run tests in parallel to cut total runtime.
JUnit 5 Example:
Create src/test/resources/junit-platform.properties
:
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = concurrent
Make sure tests don’t conflict over shared resources. If they do, consider using unique test data or test containers that can safely run in parallel.
7. Mock or Stub External Services
Why:
Hitting real APIs or external systems during tests slows them down.
Example with WireMock:
@SpringBootTest
@AutoConfigureWireMock(port = 0)
class ExternalServiceIntegrationTest {
@Test
void shouldReturnDataFromMockedService() {
WireMock.stubFor(get(urlEqualTo("/data"))
.willReturn(aResponse().withBody("{\"value\":\"mocked\"}")));
// Perform your test logic against the mocked endpoint
// ...
}
}
This avoids network latency, making tests much faster and more reliable.
8. Profiling and Identifying Bottlenecks
Don’t guess — measure! Use tools like Maven’s -X
or Gradle’s --scan
to see which tests are slow. Then target those tests with the techniques above. Maybe it’s a single large integration test that loads too many beans. Maybe it’s an external call or a database initialization. Focus on the real troublemakers.
In Summary:
- Context Minimization: Use test slices like
@WebMvcTest
or@DataJpaTest
to avoid unnecessary beans. - Context Reuse: Keep test configurations consistent so Spring can cache and reuse the context.
- Plain JUnit Tests: Skip Spring altogether when testing simple logic.
- Integration Test Strategy: Run them selectively and in dedicated build phases.
- Parallel Execution: Leverage multiple cores to run tests faster.
- Mock External Services: Avoid slow network calls during tests.
- Identify Bottlenecks: Profile and fix what’s truly slow.
By applying these tactics, you’ll likely see test durations drop significantly. This means quicker feedback loops, more productivity, and more confidence in running your tests as frequently as you need. Enjoy a snappier, more efficient testing environment!