Testing in Spring Boot
Tests are how you keep a Spring Boot application changeable without fear. Spring Boot ships a rich testing toolkit out of the box and a layered set of test slices that let you load only the part of the application context a given test needs. This section walks from plain JUnit 5 up to full end-to-end tests with Testcontainers.
The testing pyramid
A healthy suite has many fast, isolated tests at the bottom and a few slow, realistic ones at the top. Spring Boot maps cleanly onto this shape.
| Layer | What it tests | Spring involvement | Speed |
|---|---|---|---|
| Unit | One class in isolation | None — plain JUnit + Mockito | Milliseconds |
| Slice | One layer (web, JPA, JSON) | Partial context | Fast |
| Integration | Wired components together | Full / large context | Slower |
| End-to-end | Real HTTP + real DB | Full context + Testcontainers | Slowest |
Tip: Write the bulk of your logic so it can be covered by unit tests with no Spring context at all. Reserve
@SpringBootTestfor the handful of paths that genuinely need the whole application wired together.
spring-boot-starter-test
A single starter brings in everything you need. It is added with test scope by Spring Initializr.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
That one line bundles the libraries you reach for constantly:
| Library | Purpose |
|---|---|
| JUnit 5 (Jupiter) | The test engine — @Test, lifecycle, assertions |
| Spring Test & Spring Boot Test | @SpringBootTest, slices, MockMvc, TestRestTemplate |
| AssertJ | Fluent assertThat(...) assertions |
| Mockito | Mocking and stubbing collaborators |
| Hamcrest | Matcher library (used by MockMvc jsonPath) |
| JSONassert / JsonPath | Asserting on JSON documents |
| Awaitility | Testing asynchronous code |
Unit vs slice vs integration
A unit test instantiates one class directly and mocks its collaborators. No Spring context starts, so it runs in milliseconds.
class PriceCalculatorTest {
@Test
void appliesTenPercentDiscount() {
var calculator = new PriceCalculator();
assertThat(calculator.discounted(100, 10)).isEqualTo(90);
}
}
A slice test boots a narrow, auto-configured part of the context. @WebMvcTest loads the MVC layer but not your repositories; @DataJpaTest loads JPA and an embedded database but not your controllers. This is faster and more focused than a full context.
An integration test with @SpringBootTest starts the entire application context — every bean, configuration, and auto-configuration — optionally on a real HTTP port. Use it when interaction between layers is the thing under test.
Test slices overview
Each slice is a composed annotation that disables full auto-configuration and enables only what its layer needs. They keep tests fast and intent obvious.
| Slice | Loads | Typical use |
|---|---|---|
@WebMvcTest | Controllers, filters, MockMvc | Testing REST endpoints |
@DataJpaTest | JPA, repositories, embedded DB | Testing queries |
@JsonTest | Jackson/Gson serialization | Verifying JSON mapping |
@RestClientTest | RestClient/RestTemplate + mock server | Testing HTTP clients |
@DataMongoTest | Spring Data MongoDB | Testing Mongo repositories |
@WebFluxTest | WebFlux controllers + WebTestClient | Reactive endpoints |
Note: Inside a slice you replace the layers you did not load with mocks. In a
@WebMvcTestyou supply the service layer with@MockitoBean— the Spring Boot 3.4+ replacement for the deprecated@MockBean.
A first runnable test
The Spring Initializr always generates one context-load test. If it passes, your beans wire together correctly.
@SpringBootTest
class ApplicationTests {
@Test
void contextLoads() {
// Fails if any bean cannot be created
}
}
Run it with Maven:
./mvnw test
Output:
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS
In This Section
- JUnit 5 Basics — the test engine: lifecycle, assertions, parameterized tests.
- Mockito — mocking collaborators for pure unit tests.
- @SpringBootTest — full-context integration tests.
- @WebMvcTest & MockMvc — slice-testing controllers.
- @DataJpaTest — slice-testing repositories.
- Integration Testing — end-to-end tests over real HTTP.
- Testcontainers — real databases in disposable containers.
- REST Assured — a fluent DSL for HTTP API tests.
- Mocking Service Layers — strategies and trade-offs for test doubles.