Test Slices

Why Test Slices Matter

Spring Boot test slices (@WebMvcTest, @DataJpaTest) load minimal ApplicationContext for specific layers, reducing test startup from 10+ seconds (@SpringBootTest full context) to <2 seconds (slice). In production test suites with 1000+ tests, slice testing saves 2+ hours of CI/CD time by loading only required beans (controllers without services, repositories without web layer).

Solution: @WebMvcTest for controllers, @DataJpaTest for repositories.

@WebMvcTest(DonationController.class)
// => Only loads web layer: DonationController + Spring MVC infrastructure
// => NO services, repositories, or database
class DonationControllerTest {

    @Autowired
    private MockMvc mockMvc;  // => Test Spring MVC without HTTP

    @MockBean  // => Mock service (not loaded in web slice)
    private DonationService donationService;

    @Test
    void shouldReturnDonation() throws Exception {
        when(donationService.findById(1L))
            .thenReturn(new DonationResponse(1L, BigDecimal.valueOf(1000)));

        mockMvc.perform(get("/api/donations/1"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.id").value(1))
            .andExpect(jsonPath("$.amount").value(1000));
    }
}

@DataJpaTest (repository slice):

@DataJpaTest  // => Only loads JPA infrastructure: repositories + embedded database
// => NO controllers, services, or web layer
class DonationRepositoryTest {

    @Autowired
    private DonationRepository repository;  // => Real repository

    @Autowired
    private TestEntityManager entityManager;  // => Test helper for JPA

    @Test
    void shouldFindByDonorName() {
        ZakatDonation donation = new ZakatDonation();
        donation.setDonorName("Ahmad");
        donation.setAmount(BigDecimal.valueOf(1000));
        entityManager.persist(donation);

        List<ZakatDonation> found = repository.findByDonorName("Ahmad");

        assertThat(found).hasSize(1);
        assertThat(found.get(0).getAmount()).isEqualTo(BigDecimal.valueOf(1000));
    }
}

Performance comparison:

Test TypeStartup TimeBeans LoadedUse Case
@SpringBootTest10-15sAll (~500)End-to-end integration
@WebMvcTest<2sWeb layer only (~50)Controller logic
@DataJpaTest<2sJPA layer only (~30)Repository queries

Trade-offs: Test slices for fast feedback (unit-like speed for integration tests). @SpringBootTest for critical flows.

Next Steps

Last updated