google-site-verification: google61fe8ba583a51912.html
Spring Boot Test Slices in Java

Introduction

Spring Boot Test Slices are specialized testing annotations that load only specific parts of your application context, making tests faster and more focused. Instead of loading the entire application context, slices allow you to test specific layers (web, data, security) in isolation.

Maven Dependencies

<dependencies> <!-- Spring Boot Test Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Testcontainers for integration tests --> <dependency> <groupId>org.testcontainers</groupId> <artifactId>junit-jupiter</artifactId> <scope>test</scope> </dependency> <!-- Database testing --> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>test</scope> </dependency> </dependencies>

Data Layer Testing

@DataJpaTest - JPA Repository Testing

import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; @DataJpaTest class UserRepositoryTest { @Autowired private TestEntityManager entityManager; @Autowired private UserRepository userRepository; @Test void whenFindByEmail_thenReturnUser() { // given User user = User.builder() .email("[email protected]") .firstName("John") .lastName("Doe") .build(); entityManager.persist(user); entityManager.flush(); // when User found = userRepository.findByEmail("[email protected]"); // then assertThat(found).isNotNull(); assertThat(found.getEmail()).isEqualTo("[email protected]"); } @Test void whenFindByNonExistentEmail_thenReturnNull() { // when User found = userRepository.findByEmail("[email protected]"); // then assertThat(found).isNull(); } @Test void shouldPersistUserWithAuditFields() { // given User user = User.builder() .email("[email protected]") .firstName("Audit") .lastName("User") .build(); // when User saved = userRepository.save(user); // then assertThat(saved.getId()).isNotNull(); assertThat(saved.getCreatedAt()).isNotNull(); assertThat(saved.getUpdatedAt()).isNotNull(); } } // Entity class @Entity @Table(name = "users") @Builder @NoArgsConstructor @AllArgsConstructor @Data public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(unique = true, nullable = false) private String email; private String firstName; private String lastName; @CreationTimestamp private LocalDateTime createdAt; @UpdateTimestamp private LocalDateTime updatedAt; } // Repository interface public interface UserRepository extends JpaRepository<User, Long> { User findByEmail(String email); List<User> findByLastName(String lastName); Optional<User> findByIdAndEmail(Long id, String email); }

@DataJpaTest with Testcontainers

@DataJpaTest @TestPropertySource(properties = { "spring.test.database.replace=NONE", "spring.datasource.url=jdbc:tc:postgresql:15-alpine:///testdb" }) class UserRepositoryWithTestcontainersTest { @Autowired private UserRepository userRepository; @Autowired private TestEntityManager entityManager; @Test void shouldWorkWithRealPostgreSQL() { User user = User.builder() .email("[email protected]") .firstName("Postgres") .lastName("User") .build(); User saved = userRepository.save(user); assertThat(saved.getId()).isNotNull(); assertThat(userRepository.count()).isEqualTo(1); } }

@JdbcTest - JDBC Testing

import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest; import org.springframework.jdbc.core.JdbcTemplate; @JdbcTest class UserJdbcRepositoryTest { @Autowired private JdbcTemplate jdbcTemplate; @Test void shouldCountUsers() { // given jdbcTemplate.execute("CREATE TABLE users (id BIGINT PRIMARY KEY, email VARCHAR(255))"); jdbcTemplate.update("INSERT INTO users (id, email) VALUES (?, ?)", 1L, "[email protected]"); // when Integer count = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM users", Integer.class); // then assertThat(count).isEqualTo(1); } @Test void shouldInsertUser() { // given jdbcTemplate.execute("CREATE TABLE users (id BIGINT PRIMARY KEY, email VARCHAR(255))"); // when int affectedRows = jdbcTemplate.update( "INSERT INTO users (id, email) VALUES (?, ?)", 2L, "[email protected]" ); // then assertThat(affectedRows).isEqualTo(1); String email = jdbcTemplate.queryForObject( "SELECT email FROM users WHERE id = ?", String.class, 2L ); assertThat(email).isEqualTo("[email protected]"); } }

@DataMongoTest - MongoDB Testing

import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; import org.springframework.data.mongodb.core.MongoTemplate; @DataMongoTest class UserDocumentRepositoryTest { @Autowired private MongoTemplate mongoTemplate; @Autowired private UserDocumentRepository userRepository; @Test void shouldSaveAndFindUser() { // given UserDocument user = UserDocument.builder() .username("mongouser") .email("[email protected]") .build(); // when UserDocument saved = userRepository.save(user); // then assertThat(saved.getId()).isNotNull(); assertThat(userRepository.findByUsername("mongouser")) .isPresent() .get() .extracting(UserDocument::getEmail) .isEqualTo("[email protected]"); } @Test void shouldFindByEmailUsingMongoTemplate() { // given UserDocument user = UserDocument.builder() .username("templateuser") .email("[email protected]") .build(); mongoTemplate.save(user); // when UserDocument found = mongoTemplate.findOne( Query.query(Criteria.where("email").is("[email protected]")), UserDocument.class ); // then assertThat(found).isNotNull(); assertThat(found.getUsername()).isEqualTo("templateuser"); } } @Document(collection = "users") @Data @Builder @NoArgsConstructor @AllArgsConstructor class UserDocument { @Id private String id; private String username; private String email; private LocalDateTime createdAt; } public interface UserDocumentRepository extends MongoRepository<UserDocument, String> { Optional<UserDocument> findByUsername(String username); List<UserDocument> findByEmailContaining(String email); }

Web Layer Testing

@WebMvcTest - Controller Testing

import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; @WebMvcTest(UserController.class) class UserControllerTest { @Autowired private MockMvc mockMvc; @MockBean private UserService userService; @Autowired private ObjectMapper objectMapper; @Test void shouldReturnUser() throws Exception { // given UserResponse userResponse = UserResponse.builder() .id(1L) .email("[email protected]") .firstName("John") .lastName("Doe") .build(); when(userService.getUserById(1L)).thenReturn(userResponse); // when & then mockMvc.perform(get("/api/users/1") .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.id").value(1L)) .andExpect(jsonPath("$.email").value("[email protected]")) .andExpect(jsonPath("$.firstName").value("John")) .andExpect(jsonPath("$.lastName").value("Doe")); } @Test void shouldCreateUser() throws Exception { // given CreateUserRequest request = CreateUserRequest.builder() .email("[email protected]") .firstName("Jane") .lastName("Smith") .build(); UserResponse response = UserResponse.builder() .id(1L) .email("[email protected]") .firstName("Jane") .lastName("Smith") .build(); when(userService.createUser(any(CreateUserRequest.class))).thenReturn(response); // when & then mockMvc.perform(post("/api/users") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(request))) .andExpect(status().isCreated()) .andExpect(jsonPath("$.id").value(1L)) .andExpect(jsonPath("$.email").value("[email protected]")); verify(userService).createUser(any(CreateUserRequest.class)); } @Test void shouldReturn404WhenUserNotFound() throws Exception { // given when(userService.getUserById(999L)) .thenThrow(new UserNotFoundException("User not found")); // when & then mockMvc.perform(get("/api/users/999")) .andExpect(status().isNotFound()) .andExpect(jsonPath("$.message").value("User not found")); } @Test void shouldValidateCreateUserRequest() throws Exception { // given - invalid request CreateUserRequest invalidRequest = CreateUserRequest.builder() .email("invalid-email") // invalid email .firstName("") // empty first name .build(); // when & then mockMvc.perform(post("/api/users") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(invalidRequest))) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.errors").isArray()); } } // Controller class @RestController @RequestMapping("/api/users") @RequiredArgsConstructor @Validated public class UserController { private final UserService userService; @GetMapping("/{id}") public UserResponse getUser(@PathVariable Long id) { return userService.getUserById(id); } @PostMapping public ResponseEntity<UserResponse> createUser( @Valid @RequestBody CreateUserRequest request) { UserResponse response = userService.createUser(request); return ResponseEntity.created(URI.create("/api/users/" + response.getId())) .body(response); } @PutMapping("/{id}") public UserResponse updateUser( @PathVariable Long id, @Valid @RequestBody UpdateUserRequest request) { return userService.updateUser(id, request); } @DeleteMapping("/{id}") public ResponseEntity<Void> deleteUser(@PathVariable Long id) { userService.deleteUser(id); return ResponseEntity.noContent().build(); } } // DTO classes @Data @Builder @NoArgsConstructor @AllArgsConstructor class CreateUserRequest { @NotBlank @Email private String email; @NotBlank @Size(min = 2, max = 50) private String firstName; @NotBlank @Size(min = 2, max = 50) private String lastName; } @Data @Builder @NoArgsConstructor @AllArgsConstructor class UserResponse { private Long id; private String email; private String firstName; private String lastName; private LocalDateTime createdAt; }

@WebMvcTest with Security

@WebMvcTest(UserController.class) @WithMockUser class UserControllerSecurityTest { @Autowired private MockMvc mockMvc; @MockBean private UserService userService; @Test @WithMockUser(roles = "USER") void shouldAllowUserAccess() throws Exception { when(userService.getUserById(1L)).thenReturn(new UserResponse()); mockMvc.perform(get("/api/users/1")) .andExpect(status().isOk()); } @Test @WithMockUser(roles = "ADMIN") void shouldAllowAdminAccess() throws Exception { when(userService.getUserById(1L)).thenReturn(new UserResponse()); mockMvc.perform(get("/api/users/1")) .andExpect(status().isOk()); } @Test void shouldDenyAccessWithoutAuthentication() throws Exception { mockMvc.perform(get("/api/users/1")) .andExpect(status().isUnauthorized()); } @Test @WithMockUser(roles = "USER") void shouldDenyAccessForForbiddenEndpoint() throws Exception { mockMvc.perform(delete("/api/users/1")) .andExpect(status().isForbidden()); } }

@WebFluxTest - Reactive Controller Testing

import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.reactive.server.WebTestClient; @WebFluxTest(UserReactiveController.class) class UserReactiveControllerTest { @Autowired private WebTestClient webTestClient; @MockBean private UserReactiveService userService; @Test void shouldGetUser() { // given UserResponse userResponse = UserResponse.builder() .id(1L) .email("[email protected]") .firstName("Reactive") .lastName("User") .build(); when(userService.getUserById(1L)).thenReturn(Mono.just(userResponse)); // when & then webTestClient.get().uri("/api/reactive/users/1") .exchange() .expectStatus().isOk() .expectBody(UserResponse.class) .value(response -> { assertThat(response.getEmail()).isEqualTo("[email protected]"); assertThat(response.getFirstName()).isEqualTo("Reactive"); }); } @Test void shouldStreamUsers() { // given UserResponse user1 = UserResponse.builder().id(1L).email("[email protected]").build(); UserResponse user2 = UserResponse.builder().id(2L).email("[email protected]").build(); when(userService.getAllUsers()).thenReturn(Flux.just(user1, user2)); // when & then webTestClient.get().uri("/api/reactive/users/stream") .accept(MediaType.TEXT_EVENT_STREAM) .exchange() .expectStatus().isOk() .expectBodyList(UserResponse.class) .hasSize(2); } } @RestController @RequestMapping("/api/reactive/users") @RequiredArgsConstructor public class UserReactiveController { private final UserReactiveService userService; @GetMapping("/{id}") public Mono<UserResponse> getUser(@PathVariable Long id) { return userService.getUserById(id); } @GetMapping("/stream") public Flux<UserResponse> streamUsers() { return userService.getAllUsers().delayElements(Duration.ofMillis(100)); } }

JSON Layer Testing

@JsonTest - JSON Serialization/Deserialization Testing

import org.springframework.boot.test.autoconfigure.json.JsonTest; import org.springframework.boot.test.json.JacksonTester; @JsonTest class UserJsonTest { @Autowired private JacksonTester<UserResponse> json; @Autowired private JacksonTester<CreateUserRequest> requestJson; @Test void shouldSerializeUserResponse() throws Exception { // given UserResponse user = UserResponse.builder() .id(1L) .email("[email protected]") .firstName("John") .lastName("Doe") .createdAt(LocalDateTime.of(2023, 1, 1, 10, 0)) .build(); // when & then assertThat(json.write(user)).isEqualToJson("expected-user.json"); assertThat(json.write(user)).hasJsonPathStringValue("@.email"); assertThat(json.write(user)).extractingJsonPathStringValue("@.email") .isEqualTo("[email protected]"); } @Test void shouldDeserializeUserResponse() throws Exception { // given String content = """ { "id": 1, "email": "[email protected]", "firstName": "John", "lastName": "Doe", "createdAt": "2023-01-01T10:00:00" } """; // when & then assertThat(json.parse(content)) .isEqualTo(UserResponse.builder() .id(1L) .email("[email protected]") .firstName("John") .lastName("Doe") .createdAt(LocalDateTime.of(2023, 1, 1, 10, 0)) .build()); assertThat(json.parseObject(content).getEmail()).isEqualTo("[email protected]"); } @Test void shouldDeserializeCreateUserRequest() throws Exception { // given String content = """ { "email": "[email protected]", "firstName": "Jane", "lastName": "Smith" } """; // when & then assertThat(requestJson.parse(content)) .isEqualTo(CreateUserRequest.builder() .email("[email protected]") .firstName("Jane") .lastName("Smith") .build()); } @Test void shouldFailDeserializationWithInvalidEmail() throws Exception { // given String invalidContent = """ { "email": "invalid-email", "firstName": "John", "lastName": "Doe" } """; // when & then assertThatThrownBy(() -> requestJson.parse(invalidContent)) .isInstanceOf(JsonParseException.class); } } // expected-user.json { "id": 1, "email": "[email protected]", "firstName": "John", "lastName": "Doe", "createdAt": "2023-01-01T10:00:00" }

Service Layer Testing

Mocking Dependencies in Service Tests

@ExtendWith(MockitoExtension.class) class UserServiceTest { @Mock private UserRepository userRepository; @Mock private EmailService emailService; @Mock private PasswordEncoder passwordEncoder; @InjectMocks private UserService userService; @Test void shouldCreateUserSuccessfully() { // given CreateUserRequest request = CreateUserRequest.builder() .email("[email protected]") .firstName("John") .lastName("Doe") .build(); User user = User.builder() .id(1L) .email("[email protected]") .firstName("John") .lastName("Doe") .build(); when(userRepository.save(any(User.class))).thenReturn(user); when(passwordEncoder.encode(anyString())).thenReturn("encodedPassword"); doNothing().when(emailService).sendWelcomeEmail(anyString()); // when UserResponse response = userService.createUser(request); // then assertThat(response.getId()).isEqualTo(1L); assertThat(response.getEmail()).isEqualTo("[email protected]"); verify(userRepository).save(any(User.class)); verify(emailService).sendWelcomeEmail("[email protected]"); } @Test void shouldThrowExceptionWhenEmailExists() { // given CreateUserRequest request = CreateUserRequest.builder() .email("[email protected]") .firstName("John") .lastName("Doe") .build(); when(userRepository.findByEmail("[email protected]")) .thenReturn(new User()); // when & then assertThatThrownBy(() -> userService.createUser(request)) .isInstanceOf(DuplicateEmailException.class) .hasMessage("Email already exists: [email protected]"); verify(userRepository, never()).save(any(User.class)); } @Test void shouldUpdateUser() { // given Long userId = 1L; UpdateUserRequest request = UpdateUserRequest.builder() .firstName("Updated") .lastName("Name") .build(); User existingUser = User.builder() .id(userId) .email("[email protected]") .firstName("Original") .lastName("User") .build(); User updatedUser = User.builder() .id(userId) .email("[email protected]") .firstName("Updated") .lastName("Name") .build(); when(userRepository.findById(userId)).thenReturn(Optional.of(existingUser)); when(userRepository.save(any(User.class))).thenReturn(updatedUser); // when UserResponse response = userService.updateUser(userId, request); // then assertThat(response.getFirstName()).isEqualTo("Updated"); assertThat(response.getLastName()).isEqualTo("Name"); verify(userRepository).save(existingUser); } @Test void shouldThrowExceptionWhenUserNotFoundForUpdate() { // given Long userId = 999L; UpdateUserRequest request = UpdateUserRequest.builder().build(); when(userRepository.findById(userId)).thenReturn(Optional.empty()); // when & then assertThatThrownBy(() -> userService.updateUser(userId, request)) .isInstanceOf(UserNotFoundException.class) .hasMessage("User not found with id: 999"); } }

Configuration Testing

@Import and Test Configuration

@WebMvcTest(UserController.class) @Import({UserService.class, SecurityConfig.class}) class UserControllerWithImportsTest { @Autowired private MockMvc mockMvc; @MockBean private UserRepository userRepository; @MockBean private EmailService emailService; @Test void shouldWorkWithImportedConfigurations() throws Exception { // Test implementation } } @TestConfiguration class TestServiceConfiguration { @Bean @Primary public UserService testUserService() { return new TestUserService(); } @Bean public PasswordEncoder testPasswordEncoder() { return new BCryptPasswordEncoder(); } } @WebMvcTest(UserController.class) @Import(TestServiceConfiguration.class) class UserControllerWithTestConfigurationTest { @Autowired private UserService userService; // Uses the test bean @Test void shouldUseTestConfiguration() { // Test implementation } }

Custom Test Slices

Creating Custom Test Slices

// Custom annotation for service layer testing @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @BootstrapWith(SpringBootTestContextBootstrapper.class) @OverrideAutoConfiguration(enabled = false) @TypeExcludeFilters(ServiceTypeExcludeFilter.class) @AutoConfigureCache @AutoConfigureMetrics @ServiceTest public @interface ServiceSliceTest { @PropertyMapping("spring.test.service.enabled") boolean enabled() default true; Class<?>[] services() default {}; } // Custom type exclude filter class ServiceTypeExcludeFilter extends TypeExcludeFilter { private final ServiceSliceTest annotation; ServiceTypeExcludeFilter(BeanFactory beanFactory, ServiceSliceTest annotation) { this.annotation = annotation; } @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { // Custom exclusion logic for services return !isServiceComponent(metadataReader) && !isConfiguration(metadataReader); } private boolean isServiceComponent(MetadataReader metadataReader) { // Implementation to detect service components return metadataReader.getClassMetadata().getClassName().contains("Service"); } } // Auto-configuration for service slice @AutoConfiguration @ConditionalOnWebApplication @Import(ServiceSliceTestConfiguration.class) public class ServiceSliceAutoConfiguration { @Bean @ConditionalOnMissingBean public UserService userService() { return new UserService(); } } // Using the custom slice @ServiceSliceTest(services = {UserService.class, EmailService.class}) class CustomServiceSliceTest { @Autowired private UserService userService; @MockBean private UserRepository userRepository; @Test void shouldUseCustomSlice() { // Test with custom slice configuration } }

Integration Test Slices

@SpringBootTest with Test Slices

@SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { "spring.datasource.url=jdbc:h2:mem:testdb", "spring.jpa.hibernate.ddl-auto=create-drop" } ) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY) @TestPropertySource(locations = "classpath:application-test.properties") class UserIntegrationTest { @Autowired private TestRestTemplate restTemplate; @Autowired private UserRepository userRepository; @LocalServerPort private int port; @BeforeEach void setUp() { userRepository.deleteAll(); } @Test void shouldCreateUserThroughAllLayers() { // given CreateUserRequest request = CreateUserRequest.builder() .email("[email protected]") .firstName("Integration") .lastName("Test") .build(); // when ResponseEntity<UserResponse> response = restTemplate.postForEntity( "http://localhost:" + port + "/api/users", request, UserResponse.class ); // then assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); assertThat(response.getBody()).isNotNull(); assertThat(response.getBody().getEmail()).isEqualTo("[email protected]"); // Verify database assertThat(userRepository.count()).isEqualTo(1); assertThat(userRepository.findByEmail("[email protected]")).isNotNull(); } @Test void shouldGetUserThroughAllLayers() { // given User user = User.builder() .email("[email protected]") .firstName("Get") .lastName("User") .build(); User saved = userRepository.save(user); // when ResponseEntity<UserResponse> response = restTemplate.getForEntity( "http://localhost:" + port + "/api/users/" + saved.getId(), UserResponse.class ); // then assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(response.getBody()).isNotNull(); assertThat(response.getBody().getEmail()).isEqualTo("[email protected]"); } }

Performance Testing with Slices

Benchmarking Test Slices

class TestSlicePerformanceTest { @Test void compareTestSliceStartupTimes() { // Measure @DataJpaTest startup time long startTime = System.currentTimeMillis(); try (ConfigurableApplicationContext context = new SpringApplicationBuilder(DataJpaTestConfig.class) .run()) { long dataJpaTime = System.currentTimeMillis() - startTime; System.out.println("@DataJpaTest startup: " + dataJpaTime + "ms"); } // Measure @WebMvcTest startup time startTime = System.currentTimeMillis(); try (ConfigurableApplicationContext context = new SpringApplicationBuilder(WebMvcTestConfig.class) .run()) { long webMvcTime = System.currentTimeMillis() - startTime; System.out.println("@WebMvcTest startup: " + webMvcTime + "ms"); } // Measure @SpringBootTest startup time startTime = System.currentTimeMillis(); try (ConfigurableApplicationContext context = new SpringApplicationBuilder(FullAppTestConfig.class) .run()) { long fullAppTime = System.currentTimeMillis() - startTime; System.out.println("@SpringBootTest startup: " + fullAppTime + "ms"); } } @DataJpaTest static class DataJpaTestConfig {} @WebMvcTest static class WebMvcTestConfig {} @SpringBootTest static class FullAppTestConfig {} }

Best Practices

Test Organization and Structure

// Base test class for common configuration @SpringBootTest @Testcontainers @ActiveProfiles("test") @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) public abstract class BaseIntegrationTest { @Container protected static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15-alpine") .withDatabaseName("testdb") .withUsername("test") .withPassword("test"); @DynamicPropertySource static void configureProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", postgres::getJdbcUrl); registry.add("spring.datasource.username", postgres::getUsername); registry.add("spring.datasource.password", postgres::getPassword); } @BeforeEach void setUp() { // Common setup logic } @AfterEach void tearDown() { // Common cleanup logic } } // Repository tests @DataJpaTest @Import(TestConfiguration.class) class UserRepositoryTest extends BaseIntegrationTest { @Test void repositorySpecificTest() { // Test implementation } } // Controller tests @WebMvcTest(UserController.class) @WithMockUser class UserControllerTest { @Test void controllerSpecificTest() { // Test implementation } } // Service tests @ExtendWith(MockitoExtension.class) class UserServiceTest { @Test void serviceSpecificTest() { // Test implementation } }

Conclusion

Spring Boot Test Slices provide a powerful way to write focused, fast, and maintainable tests:

  • @DataJpaTest: For testing JPA components with an embedded database
  • @WebMvcTest: For testing MVC controllers with mocked dependencies
  • @WebFluxTest: For testing reactive web controllers
  • @JsonTest: For testing JSON serialization/deserialization
  • @DataMongoTest: For testing MongoDB components
  • @JdbcTest: For testing JDBC components

Key Benefits:

  • Faster Tests: Load only necessary components
  • Focused Testing: Test specific layers in isolation
  • Better Maintainability: Clear separation of concerns
  • Reduced Complexity: Simplified test configuration

When to Use Which Slice:

  • Use @DataJpaTest for repository layer testing
  • Use @WebMvcTest for web layer testing
  • Use @JsonTest for serialization testing
  • Use @SpringBootTest for full integration testing
  • Use custom slices for domain-specific testing needs

By leveraging test slices appropriately, you can create a comprehensive test pyramid with fast, reliable tests at every level of your application.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper