Home/Learn/Spring Boot/@SpringBootTest

@SpringBootTest

Intermediate
Testing

@SpringBootTest loads the full application context for integration tests; use webEnvironment=RANDOM_PORT for tests that exercise the real HTTP stack.

Overview

@SpringBootTest is the annotation for Spring Boot integration tests. It bootstraps the full ApplicationContext — all beans, auto-configuration, embedded server, and database connections — making it the closest approximation to running the real application in a test. This completeness is both its strength (high confidence) and its cost (slow startup). Spring Boot provides several test slice annotations (@WebMvcTest, @DataJpaTest, @JsonTest) that load only a subset of the context for faster, more focused tests. Knowing when to use each is the difference between a maintainable test suite and one that takes 10 minutes to run.

@SpringBootTest — Full Context Integration Test

webEnvironment controls the embedded server: - `MOCK` (default) — no real server; use MockMvc or WebTestClient - `RANDOM_PORT` — starts a real Tomcat on a random port; use TestRestTemplate or WebTestClient - `DEFINED_PORT` — real Tomcat on server.port - `NONE` — no server at all (test services/repos without HTTP)

Use RANDOM_PORT when you need to test the full HTTP stack including filters, security, and serialisation. Use MOCK for most controller tests — faster and simpler.

Java — @SpringBootTest
// Full integration test — real HTTP stack, random port
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class OrderControllerIntegrationTest {

    @Autowired
    TestRestTemplate restTemplate;  // auto-configured for RANDOM_PORT

    @Test
    void placeOrder_shouldReturn201AndOrderId() {
        OrderRequest request = new OrderRequest("PROD-1", 2);

        ResponseEntity<OrderResponse> response = restTemplate.postForEntity(
            "/api/orders", request, OrderResponse.class);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);
        assertThat(response.getBody().getOrderId()).isNotNull();
    }
}

// No server — test service layer directly
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
class OrderServiceIntegrationTest {
    @Autowired OrderService orderService;
    @Autowired OrderRepository orderRepository;

    @Test
    @Transactional
    void placeOrder_shouldPersistOrder() {
        Order order = orderService.placeOrder(new OrderRequest("PROD-1", 2));
        assertThat(orderRepository.findById(order.getId())).isPresent();
    }
}

Test Slices — Fast Focused Tests

Spring Boot test slices load only the relevant layer, skipping unneeded auto-configuration. Beans not in scope must be mocked with @MockBean.

- **@WebMvcTest** — loads only MVC layer (controllers, filters, interceptors, @ControllerAdvice). No JPA, no services — mock everything else. - **@DataJpaTest** — loads JPA + H2 in-memory DB. Rolls back each test. Test repository query correctness in isolation. - **@JsonTest** — tests JSON serialisation with Jackson alone. - **@WebFluxTest** — reactive controller slice.

Java — @WebMvcTest + @DataJpaTest
// @WebMvcTest — fast controller test, no Spring Data, no service beans
@WebMvcTest(OrderController.class)
class OrderControllerTest {

    @Autowired MockMvc mockMvc;

    @MockBean OrderService orderService;  // service not loaded — must mock

    @Test
    void getOrder_whenFound_returns200() throws Exception {
        when(orderService.findById(1L))
            .thenReturn(Optional.of(new Order(1L, "PENDING", BigDecimal.TEN)));

        mockMvc.perform(get("/api/orders/1"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.status").value("PENDING"))
            .andExpect(jsonPath("$.total").value(10.0));
    }

    @Test
    void getOrder_whenNotFound_returns404() throws Exception {
        when(orderService.findById(99L)).thenReturn(Optional.empty());

        mockMvc.perform(get("/api/orders/99"))
            .andExpect(status().isNotFound());
    }
}

// @DataJpaTest — test repository queries against real SQL
@DataJpaTest
class OrderRepositoryTest {

    @Autowired OrderRepository orderRepository;

    @Test
    void findByStatus_shouldReturnMatchingOrders() {
        orderRepository.save(new Order(null, "PENDING", BigDecimal.TEN));
        orderRepository.save(new Order(null, "SHIPPED", BigDecimal.ONE));

        List<Order> pending = orderRepository.findByStatus("PENDING");

        assertThat(pending).hasSize(1);
        assertThat(pending.get(0).getStatus()).isEqualTo("PENDING");
    }
}

@MockBean, @SpyBean and TestPropertySource

@MockBean replaces a Spring bean with a Mockito mock in the context. @SpyBean wraps the real bean with a Mockito spy (real methods unless stubbed). Use @TestPropertySource or properties attribute to override properties for a specific test.

Java — @MockBean + @SpyBean
@SpringBootTest
class PaymentServiceIntegrationTest {

    @Autowired PaymentService paymentService;

    // Replace the real PaymentGateway with a mock — avoids hitting Stripe in tests
    @MockBean PaymentGatewayClient gatewayClient;

    // Spy: wraps the real orderRepo — real methods, but can verify calls
    @SpyBean OrderRepository orderRepo;

    @Test
    void charge_shouldSaveOrderOnSuccess() {
        when(gatewayClient.charge(any())).thenReturn(new ChargeResult("ch_123", "succeeded"));

        Order order = paymentService.charge(new PaymentRequest("ord-1", BigDecimal.TEN));

        assertThat(order.getStatus()).isEqualTo("PAID");
        verify(orderRepo).save(any(Order.class));
    }
}

// Override properties for a test
@SpringBootTest
@TestPropertySource(properties = {
    "payment.gateway-url=http://localhost:8099",
    "payment.timeout-seconds=1"
})
class PaymentServiceConfigTest { }

Key Points to Remember

  • 1@SpringBootTest(webEnvironment=RANDOM_PORT) starts a real server — use TestRestTemplate for HTTP calls; best for end-to-end smoke tests.
  • 2@WebMvcTest loads only the MVC layer — fast controller tests; mock all service and repository beans with @MockBean.
  • 3@DataJpaTest loads only JPA + in-memory H2 and rolls back each test — ideal for testing @Query correctness.
  • 4@MockBean replaces the real Spring bean with a Mockito mock; @SpyBean wraps the real bean (real methods unless stubbed).
  • 5Prefer test slices over full @SpringBootTest for speed — only use @SpringBootTest for true end-to-end integration tests.
  • 6Use @TestPropertySource or @SpringBootTest(properties=…) to override application.yml values for specific tests.

Interview Questions

Sign in to ask Aria
1

What is the difference between @SpringBootTest and @WebMvcTest?

EasyAmazon
2

When would you use webEnvironment=RANDOM_PORT vs MOCK in @SpringBootTest?

MediumGoogle
3

What is the difference between @MockBean and @Mock in Spring Boot tests?

MediumFlipkart
4

How does @DataJpaTest ensure test isolation?

MediumThoughtworks
5

You have a service that calls an external payment gateway. How do you test it without making real API calls?

EasyInfosys

Ask Aria about @SpringBootTest

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…