Awesome-omni-skill spring-boot-testing

Spring Boot Testing Setup Guide

install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/spring-boot-testing" ~/.claude/skills/diegosouzapw-awesome-omni-skill-spring-boot-testing && rm -rf "$T"
manifest: skills/development/spring-boot-testing/SKILL.md
source content

Spring Boot Testing Setup Guide

This skill provides comprehensive documentation for setting up unit and integration testing in Spring Boot applications, emphasizing auto-configuration and best practices from the Baeldung reference patterns.

Overview

Spring Boot provides powerful testing support with auto-configured test annotations that bootstrap only the necessary parts of the application context. This approach ensures fast, focused tests while maintaining the benefits of Spring's dependency injection.

Note: For Spring Boot 3.4+, use

@MockitoBean
instead of
@MockBean
for mocking dependencies.
@MockitoBean
provides better performance and more consistent behavior with the latest Mockito features.

Dependencies

Add these essential testing dependencies to your

pom.xml
:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>test</scope>
</dependency>

The

spring-boot-starter-test
includes:

  • JUnit 5
  • Mockito
  • MockitoBean (Spring Boot 3.4+)
  • AssertJ
  • Hamcrest
  • Spring Test & Spring Boot Test

Testing Strategy

1. Unit Tests

  • Purpose: Test individual components in isolation
  • Speed: Fast
  • Dependencies: Mocked
  • Recommended Annotations:
    @ExtendWith(SpringExtension.class)
    ,
    @WebMvcTest
    ,
    @DataJpaTest

2. Integration Tests

  • Purpose: Test interaction between layers
  • Speed: Slower
  • Dependencies: Real or test database
  • Recommended Annotations:
    @SpringBootTest

Auto-Configured Test Annotations

Controller Layer Testing

Use

@WebMvcTest
for focused controller tests:

@ExtendWith(SpringExtension.class)
@WebMvcTest(EmployeeRestController.class)
public class EmployeeRestControllerTest {

    @Autowired
    private MockMvc mvc;

    @MockitoBean  // Use MockitoBean for Spring Boot 3.4+
    private EmployeeService service;

    @Test
    public void givenEmployees_whenGetEmployees_thenReturnJsonArray() throws Exception {
        Employee alex = new Employee("alex");
        List<Employee> allEmployees = Arrays.asList(alex);

        given(service.getAllEmployees()).willReturn(allEmployees);

        mvc.perform(get("/api/employees")
                .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$", hasSize(1)))
                .andExpect(jsonPath("$[0].name", is(alex.getName())));
    }
}

Benefits:

  • Auto-configures MockMvc
  • Loads only controller-related beans
  • Mocks dependencies with
    @MockitoBean
    (Spring Boot 3.4+) or
    @MockBean
    (older versions)
  • Fast execution

Persistence Layer Testing

Use

@DataJpaTest
for repository tests:

@ExtendWith(SpringExtension.class)
@DataJpaTest
public class EmployeeRepositoryTest {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private EmployeeRepository employeeRepository;

    @Test
    public void whenFindByName_thenReturnEmployee() {
        Employee alex = new Employee("alex");
        entityManager.persist(alex);
        entityManager.flush();

        Employee found = employeeRepository.findByName(alex.getName());

        assertThat(found.getName()).isEqualTo(alex.getName());
    }
}

Auto-configuration includes:

  • In-memory H2 database
  • Hibernate, Spring Data, DataSource
  • Entity scanning
  • SQL logging

Service Layer Testing

Use

@ExtendWith
with
@MockBean
for service tests:

@ExtendWith(SpringExtension.class)
public class EmployeeServiceTest {

    @MockitoBean  // Use MockitoBean for Spring Boot 3.4+
    private EmployeeRepository employeeRepository;

    @Autowired
    private EmployeeService employeeService;

    @BeforeEach
    public void setUp() {
        Employee alex = new Employee("alex");
        when(employeeRepository.findByName(alex.getName())).thenReturn(alex);
    }

    @Test
    public void whenValidName_thenEmployeeShouldBeFound() {
        String name = "alex";
        Employee found = employeeService.getEmployeeByName(name);

        assertThat(found.getName()).isEqualTo(name);
    }
}

Full Integration Testing

Use

@SpringBootTest
for end-to-end tests:

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@AutoConfigureMockMvc
@TestPropertySource(locations = "classpath:application-integrationtest.properties")
public class EmployeeRestControllerIntegrationTest {

    @Autowired
    private MockMvc mvc;

    @Autowired
    private EmployeeRepository repository;

    @Test
    public void givenEmployees_whenGetEmployees_thenStatus200() throws Exception {
        createTestEmployee("bob");

        mvc.perform(get("/api/employees")
                .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
                .andExpect(jsonPath("$[0].name", is("bob")));
    }

    private void createTestEmployee(String name) {
        Employee employee = new Employee(name);
        repository.save(employee);
    }
}

Test Configuration

Test-Specific Configuration

Use

@TestConfiguration
for test-specific beans:

@TestConfiguration
public class EmployeeServiceTestConfig {

    @Bean
    @Primary
    public EmployeeService employeeService() {
        return new EmployeeServiceImpl() {
            // Test-specific implementation
        };
    }
}

Import in tests:

@ExtendWith(SpringExtension.class)
@Import(EmployeeServiceTestConfig.class)
public class EmployeeServiceTest {
    // Test implementation
}

Test Properties

Create test-specific configuration files. Spring Boot supports both

.properties
and
.yml
formats:

For

.properties
format (application-integrationtest.properties):

spring.datasource.url=jdbc:h2:mem:test
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop
logging.level.org.hibernate.SQL=DEBUG

For

.yml
format (application-integrationtest.yml):

spring:
  datasource:
    url: jdbc:h2:mem:test
  jpa:
    properties:
      hibernate:
        dialect: org.hibernate.dialect.H2Dialect
    hibernate:
      ddl-auto: create-drop
logging:
  level:
    org.hibernate.SQL: DEBUG

Note: Use the same format as your main application configuration. If your project uses

application.yml
, create
application-integrationtest.yml
for consistency.

Specialized Auto-Configured Tests

WebFlux Testing

@WebFluxTest(HomeController.class)
public class HomeControllerTest {
    // Test reactive controllers
}

JSON Testing

@JsonTest
public class EmployeeJsonTest {
    @Autowired
    private JacksonTester<Employee> json;

    @Test
    public void employeeSerializationTest() throws IOException {
        Employee employee = new Employee("John");
        assertThat(json.write(employee)).isEqualToJson("expected.json");
    }
}

REST Client Testing

@RestClientTest(EmployeeClient.class)
public class EmployeeClientTest {
    @Autowired
    private MockRestServiceServer server;

    @Autowired
    private EmployeeClient client;
}

Database Testing

JDBC Testing

@JdbcTest
public class EmployeeJdbcTest {
    @Autowired
    private JdbcTemplate jdbcTemplate;
}

MongoDB Testing

@DataMongoTest
public class EmployeeMongoTest {
    @Autowired
    private MongoTemplate mongoTemplate;
}

Best Practices

1. Test Organization

  • Keep unit tests in
    src/test/java
  • Separate integration tests with
    @Test
    annotation profiles
  • Use descriptive test names

2. Auto-Configuration Priority

Always prefer auto-configured test annotations:

  • Use
    @WebMvcTest
    instead of
    @SpringBootTest
    for controller tests
  • Use
    @DataJpaTest
    instead of
    @SpringBootTest
    for repository tests
  • Use
    @SpringBootTest
    only when necessary

3. Mocking Strategy

  • Mock external dependencies with
    @MockitoBean
    (Spring Boot 3.4+) or
    @MockBean
    (older versions)
  • Use
    @TestConfiguration
    for test-specific beans
  • Avoid mocking the layer you're testing

4. Test Data Management

  • Use
    TestEntityManager
    for JPA tests
  • Clean up test data in
    @AfterEach
  • Use
    @Transactional
    for rollback behavior

5. Performance Considerations

  • Run unit tests separately from integration tests
  • Use in-memory databases for testing
  • Limit
    @SpringBootTest
    usage

Test Execution Profiles

Maven Configuration

<profiles>
    <profile>
        <id>unit-tests</id>
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <includes>
                            <include>**/*Test.java</include>
                        </includes>
                        <excludes>
                            <exclude>**/*IntegrationTest.java</exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
    <profile>
        <id>integration-tests</id>
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-failsafe-plugin</artifactId>
                    <configuration>
                        <includes>
                            <include>**/*IntegrationTest.java</include>
                        </includes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

Running Tests

# Unit tests only
mvn test -Punit-tests

# Integration tests only
mvn verify -Pintegration-tests

# All tests
mvn test

Common Patterns

Service Layer with Repository Mock

@ExtendWith(SpringExtension.class)
public class EmployeeServiceTest {

    @MockitoBean  // Use MockitoBean for Spring Boot 3.4+
    private EmployeeRepository repository;

    @InjectMocks
    @Autowired
    private EmployeeService service;

    @Test
    public void whenFindById_thenReturnEmployee() {
        // Given
        Employee employee = new Employee("John");
        when(repository.findById(1L)).thenReturn(Optional.of(employee));

        // When
        Employee found = service.findById(1L);

        // Then
        assertThat(found.getName()).isEqualTo("John");
    }
}

Controller with Service Mock

@WebMvcTest(EmployeeController.class)
public class EmployeeControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockitoBean  // Use MockitoBean for Spring Boot 3.4+
    private EmployeeService service;

    @Test
    public void getEmployee_shouldReturnEmployee() throws Exception {
        Employee employee = new Employee("John");
        when(service.findById(1L)).thenReturn(employee);

        mockMvc.perform(get("/employees/1"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.name", is("John")));
    }
}

Repository Integration Test

@DataJpaTest
@TestPropertySource(properties = {
    "spring.jpa.hibernate.ddl-auto=create-drop"
})
public class EmployeeRepositoryTest {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private EmployeeRepository repository;

    @Test
    public void findByName_shouldReturnEmployee() {
        Employee employee = new Employee("John");
        entityManager.persistAndFlush(employee);

        Optional<Employee> found = repository.findByName("John");

        assertThat(found).isPresent();
        assertThat(found.get().getName()).isEqualTo("John");
    }
}

Conclusion

Spring Boot's auto-configured test annotations provide a powerful, efficient way to structure tests. By choosing the right annotation for each test type and leveraging auto-configuration, you can create fast, maintainable test suites that provide comprehensive coverage while minimizing setup complexity.

Key takeaways:

  1. Prefer auto-configured annotations over manual configuration
  2. Choose the right test slice for the layer you're testing
  3. Mock dependencies appropriately with
    @MockitoBean
    (Spring Boot 3.4+) or
    @MockBean
    (older versions)
  4. Separate test types for better performance and organization
  5. Use test-specific configuration for specialized test needs