Springboot Tdd

affaan-m/ECC/pi/core/skills/springboot-tdd

by affaan-mef648e01899ba3e8dc6371642deaaf64b4477775No license275K starsListed Oct 9, 2026Updated Oct 9, 2026Repository updated 4 days ago

Test-driven development for Spring Boot using JUnit 5, Mockito, MockMvc, Testcontainers, and JaCoCo. Use when adding features, fixing bugs, or refactoring.

Instructions onlySoftware Development
AI-generated overview

Guides test-driven development for Spring Boot services using JUnit 5, Mockito, MockMvc, Testcontainers and JaCoCo.

What it does
Provides a TDD workflow for Spring Boot: write failing tests first, implement minimal code, refactor, then enforce coverage with JaCoCo. It supplies example test patterns for unit tests with JUnit 5 and Mockito, web-layer tests with MockMvc, integration tests with SpringBootTest, and persistence tests with DataJpaTest and Testcontainers. It also covers AssertJ assertions, test data builders, and Maven or Gradle CI commands.
When to use it
Use when adding new features or endpoints, fixing bugs, refactoring, or adding data access logic or security rules to a Spring Boot service. It targets teams wanting 80% or higher unit and integration test coverage.
Requirements
Instructions only, no scripts. Assumes a Spring Boot project with JUnit 5, Mockito, MockMvc, Testcontainers and JaCoCo, plus Maven or Gradle; Testcontainers requires a container runtime.

Spring Boot TDD Workflow

TDD guidance for Spring Boot services with 80%+ coverage (unit + integration).

When to Use

  • New features or endpoints
  • Bug fixes or refactors
  • Adding data access logic or security rules

Workflow

  1. Write tests first (they should fail)
  2. Implement minimal code to pass
  3. Refactor with tests green
  4. Enforce coverage (JaCoCo)

Unit Tests (JUnit 5 + Mockito)

java
@ExtendWith(MockitoExtension.class)class MarketServiceTest {  @Mock MarketRepository repo;  @InjectMocks MarketService service;
  @Test  void createsMarket() {    CreateMarketRequest req = new CreateMarketRequest("name", "desc", Instant.now(), List.of("cat"));    when(repo.save(any())).thenAnswer(inv -> inv.getArgument(0));
    Market result = service.create(req);
    assertThat(result.name()).isEqualTo("name");    verify(repo).save(any());  }}

Patterns:

  • Arrange-Act-Assert
  • Avoid partial mocks; prefer explicit stubbing
  • Use @ParameterizedTest for variants

Web Layer Tests (MockMvc)

java
@WebMvcTest(MarketController.class)class MarketControllerTest {  @Autowired MockMvc mockMvc;  @MockBean MarketService marketService;
  @Test  void returnsMarkets() throws Exception {    when(marketService.list(any())).thenReturn(Page.empty());
    mockMvc.perform(get("/api/markets"))        .andExpect(status().isOk())        .andExpect(jsonPath("$.content").isArray());  }}

Integration Tests (SpringBootTest)

java
@SpringBootTest@AutoConfigureMockMvc@ActiveProfiles("test")class MarketIntegrationTest {  @Autowired MockMvc mockMvc;
  @Test  void createsMarket() throws Exception {    mockMvc.perform(post("/api/markets")        .contentType(MediaType.APPLICATION_JSON)        .content("""          {"name":"Test","description":"Desc","endDate":"2030-01-01T00:00:00Z","categories":["general"]}        """))      .andExpect(status().isCreated());  }}

Persistence Tests (DataJpaTest)

java
@DataJpaTest@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)@Import(TestContainersConfig.class)class MarketRepositoryTest {  @Autowired MarketRepository repo;
  @Test  void savesAndFinds() {    MarketEntity entity = new MarketEntity();    entity.setName("Test");    repo.save(entity);
    Optional<MarketEntity> found = repo.findByName("Test");    assertThat(found).isPresent();  }}

Testcontainers

  • Use reusable containers for Postgres/Redis to mirror production
  • Wire via @DynamicPropertySource to inject JDBC URLs into Spring context

Coverage (JaCoCo)

Maven snippet:

xml
<plugin>  <groupId>org.jacoco</groupId>  <artifactId>jacoco-maven-plugin</artifactId>  <version>0.8.14</version>  <executions>    <execution>      <goals><goal>prepare-agent</goal></goals>    </execution>    <execution>      <id>report</id>      <phase>verify</phase>      <goals><goal>report</goal></goals>    </execution>  </executions></plugin>

Assertions

  • Prefer AssertJ (assertThat) for readability
  • For JSON responses, use jsonPath
  • For exceptions: assertThatThrownBy(...)

Test Data Builders

java
class MarketBuilder {  private String name = "Test";  MarketBuilder withName(String name) { this.name = name; return this; }  Market build() { return new Market(null, name, MarketStatus.ACTIVE); }}

CI Commands

  • Maven: mvn -T 4 test or mvn verify
  • Gradle: ./gradlew test jacocoTestReport

Remember: Keep tests fast, isolated, and deterministic. Test behavior, not implementation details.

Source and attribution

Source:affaan-m/ECCinpi/core/skills/springboot-tddat commitef648e0

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal