Starter for testing Spring Boot applications with libraries including JUnit Jupiter, Hamcrest and Mockito
—
Auto-configured test slices for focused testing of specific application layers with minimal context loading. Test slices load only the components necessary for testing a particular layer, improving test performance and isolation.
Auto-configured test slice for testing Spring MVC controllers with MockMvc.
/**
* Annotation for Spring MVC tests that focus only on Spring MVC components
* @since 1.4.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(WebMvcTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(WebMvcTypeExcludeFilter.class)
@AutoConfigureCache
@AutoConfigureWebMvc
@AutoConfigureMockMvc
@ImportAutoConfiguration
public @interface WebMvcTest {
/**
* Specifies the controllers to test (same as controllers)
*/
Class<?>[] value() default {};
/**
* Specifies the controllers to test
*/
Class<?>[] controllers() default {};
/**
* Determines if default filters should be used with @ComponentScan
*/
boolean useDefaultFilters() default true;
/**
* ComponentScan filters to include additional components
*/
ComponentScan.Filter[] includeFilters() default {};
/**
* ComponentScan filters to exclude components
*/
ComponentScan.Filter[] excludeFilters() default {};
/**
* Properties in form key=value to add to the Environment
*/
String[] properties() default {};
}Usage Examples:
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void getUserReturnsUser() throws Exception {
User mockUser = new User("test@example.com", "Test User");
when(userService.findByEmail("test@example.com")).thenReturn(mockUser);
mockMvc.perform(get("/users/test@example.com"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.email").value("test@example.com"))
.andExpect(jsonPath("$.name").value("Test User"));
verify(userService).findByEmail("test@example.com");
}
@Test
void createUserValidatesInput() throws Exception {
mockMvc.perform(post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content("{}"))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.errors").exists());
}
}Auto-configured test slice for testing Spring WebFlux controllers with WebTestClient.
/**
* Annotation for WebFlux tests that focus only on Spring WebFlux components
* @since 2.0.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(WebFluxTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(WebFluxTypeExcludeFilter.class)
@AutoConfigureCache
@AutoConfigureWebFlux
@AutoConfigureWebTestClient
@ImportAutoConfiguration
public @interface WebFluxTest {
/**
* Specifies the controllers to test (same as controllers)
*/
Class<?>[] value() default {};
/**
* Specifies the controllers to test
*/
Class<?>[] controllers() default {};
/**
* Determines if default filters should be used with @ComponentScan
*/
boolean useDefaultFilters() default true;
/**
* ComponentScan filters to include additional components
*/
ComponentScan.Filter[] includeFilters() default {};
/**
* ComponentScan filters to exclude components
*/
ComponentScan.Filter[] excludeFilters() default {};
/**
* Properties in form key=value to add to the Environment
*/
String[] properties() default {};
}Usage Examples:
@WebFluxTest(UserController.class)
class UserControllerWebFluxTest {
@Autowired
private WebTestClient webTestClient;
@MockBean
private UserService userService;
@Test
void getUserReturnsUser() {
User mockUser = new User("test@example.com", "Test User");
when(userService.findByEmail("test@example.com")).thenReturn(Mono.just(mockUser));
webTestClient.get()
.uri("/users/test@example.com")
.exchange()
.expectStatus().isOk()
.expectHeader().contentType(MediaType.APPLICATION_JSON)
.expectBody(User.class)
.value(user -> {
assertThat(user.getEmail()).isEqualTo("test@example.com");
assertThat(user.getName()).isEqualTo("Test User");
});
}
}Auto-configured test slice for JPA repositories using an in-memory database.
/**
* Annotation for JPA tests that focus only on JPA components
* @since 1.4.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(DataJpaTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataJpaTypeExcludeFilter.class)
@Transactional
@AutoConfigureCache
@AutoConfigureDataJpa
@AutoConfigureTestDatabase
@AutoConfigureTestEntityManager
@ImportAutoConfiguration
public @interface DataJpaTest {
/**
* Entity types to scan for
*/
Class<?>[] entities() default {};
/**
* Whether to show SQL statements
*/
boolean showSql() default true;
/**
* Determines if default filters should be used with @ComponentScan
*/
boolean useDefaultFilters() default true;
/**
* ComponentScan filters to include additional components
*/
ComponentScan.Filter[] includeFilters() default {};
/**
* ComponentScan filters to exclude components
*/
ComponentScan.Filter[] excludeFilters() default {};
/**
* Properties in form key=value to add to the Environment
*/
String[] properties() default {};
}Usage Examples:
@DataJpaTest
class UserRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private UserRepository userRepository;
@Test
void findByEmailReturnsUser() {
// Given
User user = new User("test@example.com", "Test User");
entityManager.persistAndFlush(user);
// When
Optional<User> found = userRepository.findByEmail("test@example.com");
// Then
assertThat(found).isPresent();
assertThat(found.get().getName()).isEqualTo("Test User");
}
@Test
void findByNonExistentEmailReturnsEmpty() {
Optional<User> found = userRepository.findByEmail("nonexistent@example.com");
assertThat(found).isEmpty();
}
@Test
void saveUserPersistsData() {
User user = new User("save@example.com", "Save User");
User saved = userRepository.save(user);
assertThat(saved.getId()).isNotNull();
assertThat(entityManager.find(User.class, saved.getId())).isEqualTo(saved);
}
}Auto-configured test slice for MongoDB repositories.
/**
* Annotation for MongoDB tests that focus only on MongoDB components
* @since 1.4.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(DataMongoTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataMongoTypeExcludeFilter.class)
@AutoConfigureCache
@AutoConfigureDataMongo
@ImportAutoConfiguration
public @interface DataMongoTest {
/**
* Determines if default filters should be used with @ComponentScan
*/
boolean useDefaultFilters() default true;
/**
* ComponentScan filters to include additional components
*/
ComponentScan.Filter[] includeFilters() default {};
/**
* ComponentScan filters to exclude components
*/
ComponentScan.Filter[] excludeFilters() default {};
/**
* Properties in form key=value to add to the Environment
*/
String[] properties() default {};
}Auto-configured test slice for Redis repositories.
/**
* Annotation for Redis tests that focus only on Redis components
* @since 1.4.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(DataRedisTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataRedisTypeExcludeFilter.class)
@AutoConfigureCache
@AutoConfigureDataRedis
@ImportAutoConfiguration
public @interface DataRedisTest {
/**
* Determines if default filters should be used with @ComponentScan
*/
boolean useDefaultFilters() default true;
/**
* ComponentScan filters to include additional components
*/
ComponentScan.Filter[] includeFilters() default {};
/**
* ComponentScan filters to exclude components
*/
ComponentScan.Filter[] excludeFilters() default {};
/**
* Properties in form key=value to add to the Environment
*/
String[] properties() default {};
}Auto-configured test slice for testing JSON serialization and deserialization.
/**
* Annotation for JSON tests that focus only on JSON serialization
* @since 1.4.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(JsonTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@AutoConfigureCache
@AutoConfigureJson
@AutoConfigureJsonTesters
@ImportAutoConfiguration
public @interface JsonTest {
/**
* Determines if default filters should be used with @ComponentScan
*/
boolean useDefaultFilters() default true;
/**
* ComponentScan filters to include additional components
*/
ComponentScan.Filter[] includeFilters() default {};
/**
* ComponentScan filters to exclude components
*/
ComponentScan.Filter[] excludeFilters() default {};
/**
* Properties in form key=value to add to the Environment
*/
String[] properties() default {};
}Usage Examples:
@JsonTest
class UserJsonTest {
@Autowired
private JacksonTester<User> json;
@Test
void serializeUser() throws Exception {
User user = new User("test@example.com", "Test User");
assertThat(this.json.write(user))
.hasJsonPathStringValue("@.email", "test@example.com")
.hasJsonPathStringValue("@.name", "Test User");
}
@Test
void deserializeUser() throws Exception {
String content = "{\"email\":\"test@example.com\",\"name\":\"Test User\"}";
User user = this.json.parseObject(content);
assertThat(user.getEmail()).isEqualTo("test@example.com");
assertThat(user.getName()).isEqualTo("Test User");
}
}Auto-configured test slice for testing REST clients.
/**
* Annotation for REST client tests that focus only on REST client components
* @since 1.4.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(RestClientTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(RestClientTestTypeExcludeFilter.class)
@AutoConfigureCache
@AutoConfigureWebClient
@AutoConfigureMockRestServiceServer
@ImportAutoConfiguration
public @interface RestClientTest {
/**
* Specifies the components to test (same as components)
*/
Class<?>[] value() default {};
/**
* Specifies the components to test
*/
Class<?>[] components() default {};
/**
* Determines if default filters should be used with @ComponentScan
*/
boolean useDefaultFilters() default true;
/**
* ComponentScan filters to include additional components
*/
ComponentScan.Filter[] includeFilters() default {};
/**
* ComponentScan filters to exclude components
*/
ComponentScan.Filter[] excludeFilters() default {};
/**
* Properties in form key=value to add to the Environment
*/
String[] properties() default {};
}Usage Examples:
@RestClientTest(UserClient.class)
class UserClientTest {
@Autowired
private UserClient userClient;
@Autowired
private MockRestServiceServer server;
@Test
void getUserCallsExternalService() {
// Mock external service response
this.server.expect(requestTo("/api/users/test@example.com"))
.andExpect(method(HttpMethod.GET))
.andRespond(withSuccess(
"{\"email\":\"test@example.com\",\"name\":\"Test User\"}",
MediaType.APPLICATION_JSON));
// Call client method
User user = userClient.getUser("test@example.com");
// Verify response
assertThat(user.getEmail()).isEqualTo("test@example.com");
assertThat(user.getName()).isEqualTo("Test User");
}
}Configuration for test databases in data layer tests.
/**
* Annotation to configure a test database for use in tests
* @since 1.4.0
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ImportAutoConfiguration
public @interface AutoConfigureTestDatabase {
/**
* The type of connection to use
*/
Connection connection() default Connection.EMBEDDED;
/**
* What the test database should replace
*/
Replace replace() default Replace.ANY;
/**
* Type of connection to use
*/
enum Connection {
/**
* Use an embedded in-memory database
*/
EMBEDDED,
/**
* Use any available connection
*/
ANY
}
/**
* What the test database should replace
*/
enum Replace {
/**
* Replace any DataSource bean
*/
ANY,
/**
* Replace auto-configured DataSource
*/
AUTO_CONFIGURED,
/**
* Don't replace any DataSource
*/
NONE
}
}Usage Examples:
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserRepositoryIntegrationTest {
// Uses actual database configuration instead of embedded
@Autowired
private UserRepository userRepository;
@Test
void findByEmailWithRealDatabase() {
// Test using actual database
User user = new User("real@example.com", "Real User");
userRepository.save(user);
Optional<User> found = userRepository.findByEmail("real@example.com");
assertThat(found).isPresent();
}
}Advanced patterns and configurations for test slices.
Usage Examples:
// Multiple test slices with custom configuration
@WebMvcTest
@Import({SecurityConfig.class, CustomValidator.class})
class SecureControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@WithMockUser(roles = "ADMIN")
@Test
void adminCanAccessProtectedEndpoint() throws Exception {
mockMvc.perform(get("/admin/users"))
.andExpect(status().isOk());
}
}
// Custom filters for component scanning
@WebMvcTest(
includeFilters = @ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = CustomExceptionHandler.class
),
excludeFilters = @ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = GlobalSecurityConfig.class
)
)
class FilteredWebMvcTest {
// Test implementation
}
// Test slice with custom properties
@DataJpaTest(properties = {
"spring.jpa.hibernate.ddl-auto=create-drop",
"logging.level.org.hibernate.SQL=DEBUG"
})
class CustomPropertiesDataJpaTest {
// Test implementation with custom JPA properties
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-test