home / skills / marcelorodrigo / agent-skills / spring-boot-testing

spring-boot-testing skill

/skills/spring-boot-testing

This skill helps you apply modern Spring Boot 4 testing techniques using JUnit 6 and AssertJ for efficient, reliable tests.

npx playbooks add skill marcelorodrigo/agent-skills --skill spring-boot-testing

Review the files below or copy the command above to add this skill to your agents.

Files (13)
SKILL.md
6.5 KB
---
name: spring-boot-testing
description: Expert Spring Boot 4 testing specialist that selects the best Spring Boot testing techniques for your situation with Junit 6 and AssertJ.
license: MIT
compatibility: Requires Spring Boot 4.0+, JUnit 6, AssertJ, Instancio, Java 25+
metadata:
  version: "1.0.0"
---

# Spring Boot Testing

Expert guide for testing Spring Boot 4 applications with modern patterns and best practices.

## Core Principles

1. **Test Pyramid**: Unit (fast) > Slice (focused) > Integration (complete)
2. **Right Tool**: Use the narrowest slice that gives you confidence
3. **AssertJ Style**: Fluent, readable assertions over verbose matchers
4. **Modern APIs**: Prefer MockMvcTester and RestTestClient over legacy alternatives

## Which Test Slice?

| Scenario | Annotation | Reference |
|----------|------------|-----------|
| Controller + HTTP semantics | `@WebMvcTest` | [references/webmvctest.md](references/webmvctest.md) |
| Repository + JPA queries | `@DataJpaTest` | [references/datajpatest.md](references/datajpatest.md) |
| REST client + external APIs | `@RestClientTest` | [references/restclienttest.md](references/restclienttest.md) |
| JSON (de)serialization | `@JsonTest` | See references/test-slices-overview.md |
| Full application | `@SpringBootTest` | See references/test-slices-overview.md |

## Test Slices Reference

- [references/test-slices-overview.md](references/test-slices-overview.md) - Decision matrix and comparison
- [references/webmvctest.md](references/webmvctest.md) - Web layer with MockMvc
- [references/datajpatest.md](references/datajpatest.md) - Data layer with Testcontainers
- [references/restclienttest.md](references/restclienttest.md) - REST client testing

## Testing Tools Reference

- [references/mockmvc-tester.md](references/mockmvc-tester.md) - AssertJ-style MockMvc (recommended)
- [references/mockmvc-classic.md](references/mockmvc-classic.md) - Traditional MockMvc
- [references/resttestclient.md](references/resttestclient.md) - Spring Boot 4+ REST client
- [references/mockitobean.md](references/mockitobean.md) - Mocking dependencies

## Assertion Libraries

- [references/assertj-basics.md](references/assertj-basics.md) - Core AssertJ patterns
- [references/assertj-collections.md](references/assertj-collections.md) - Collection assertions

## Testcontainers

- [references/testcontainers-jdbc.md](references/testcontainers-jdbc.md) - PostgreSQL, MySQL, etc.

## Test Data Generation

- [references/instancio.md](references/instancio.md) - Generate complex test objects (3+ properties)

## Performance & Migration

- [references/context-caching.md](references/context-caching.md) - Speed up test suites
- [references/sb4-migration.md](references/sb4-migration.md) - Spring Boot 4.0 changes

## Quick Decision Tree

```
Testing a controller endpoint?
  Yes → @WebMvcTest with MockMvcTester

Testing repository queries?
  Yes → @DataJpaTest with Testcontainers (real DB)

Testing business logic in service?
  Yes → Plain JUnit + Mockito (no Spring context)

Testing external API client?
  Yes → @RestClientTest with MockRestServiceServer

Testing JSON mapping?
  Yes → @JsonTest

Need full integration test?
  Yes → @SpringBootTest with minimal context config
```

## Spring Boot 4 Highlights

- **RestTestClient**: Modern alternative to TestRestTemplate
- **@MockitoBean**: Replaces @MockBean (deprecated)
- **MockMvcTester**: AssertJ-style assertions for web tests
- **Modular starters**: Technology-specific test starters
- **Context pausing**: Automatic pausing of cached contexts (Spring Framework 7)

## Testing Best Practices

### Code Complexity Assessment

When a method or class is too complex to test effectively:

1. **Analyze complexity** - If you need more than 5-7 test cases to cover a single method, it's likely too complex
2. **Recommend refactoring** - Suggest breaking the code into smaller, focused functions
3. **User decision** - If the user agrees to refactor, help identify extraction points
4. **Proceed if needed** - If the user decides to continue with the complex code, implement tests despite the difficulty

**Example of refactoring recommendation:**
```java
// Before: Complex method hard to test
public Order processOrder(OrderRequest request) {
  // Validation, discount calculation, payment, inventory, notification...
  // 50+ lines of mixed concerns
}

// After: Refactored into testable units
public Order processOrder(OrderRequest request) {
  validateOrder(request);
  var order = createOrder(request);
  applyDiscount(order);
  processPayment(order);
  updateInventory(order);
  sendNotification(order);
  return order;
}
```

### Avoid Code Redundancy

Create helper methods for commonly used objects and mock setup to enhance readability and maintainability.

### Test Organization with @DisplayName

Use descriptive display names to clarify test intent:

```java
@Test
@DisplayName("Should calculate discount for VIP customer")
void shouldCalculateDiscountForVip() { }

@Test
@DisplayName("Should reject order when customer has insufficient credit")
void shouldRejectOrderForInsufficientCredit() { }
```

### Test Coverage Order

Always structure tests in this order:

1. **Main scenario** - The happy path, most common use case
2. **Other paths** - Alternative valid scenarios, edge cases
3. **Exceptions/Errors** - Invalid inputs, error conditions, failure modes

### Test Production Scenarios

Write tests with real production scenarios in mind. This makes tests more relatable and helps understand code behavior in actual production cases.

### Test Coverage Goals

Aim for 80% code coverage as a practical balance between quality and effort. Higher coverage is beneficial but not the only goal.

Use Jacoco maven plugin for coverage reporting and tracking.


**Coverage Rules:**
- 80+% coverage minimum
- Focus on meaningful assertions, not just execution

**What to Prioritize:**
1. Business-critical paths (payment processing, order validation)
2. Complex algorithms (pricing, discount calculations)
3. Error handling (exceptions, edge cases)
4. Integration points (external APIs, databases)

## Dependencies (Spring Boot 4)

```xml
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>

<!-- For WebMvc tests -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-webmvc-test</artifactId>
  <scope>test</scope>
</dependency>

<!-- For Testcontainers -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-testcontainers</artifactId>
  <scope>test</scope>
</dependency>
```

Overview

This skill is an expert Spring Boot 4 testing consultant that recommends the right test slice, tooling, and assertions for your codebase using JUnit 6 and AssertJ. It focuses on practical, modern testing patterns like MockMvcTester, RestTestClient, @MockitoBean, and Testcontainers to get reliable, fast feedback. It helps you balance test speed, scope, and confidence while improving test design and coverage.

How this skill works

I assess the code under test and map it to the narrowest test slice that provides confidence (unit → slice → integration). I recommend concrete annotations (@WebMvcTest, @DataJpaTest, @RestClientTest, @JsonTest, @SpringBootTest), the appropriate test tooling (MockMvcTester, RestTestClient, Testcontainers), and AssertJ-style assertions. I also provide refactoring suggestions for overly complex methods, test organization patterns, and strategies to speed up suites (context caching, focused test starters).

When to use it

  • Testing controller endpoints and HTTP semantics → use @WebMvcTest with MockMvcTester
  • Verifying JPA repositories and queries → use @DataJpaTest with Testcontainers (real DB)
  • Testing REST clients and external APIs → use @RestClientTest with MockRestServiceServer
  • Validating JSON (de)serialization → use @JsonTest
  • Full end-to-end or context-sensitive behavior → use @SpringBootTest with minimal config
  • Unit-testing service logic without Spring context → plain JUnit 6 + Mockito (@MockitoBean for beans when needed)

Best practices

  • Pick the narrowest slice that proves behavior to keep tests fast and focused
  • Use AssertJ fluent assertions for readable, maintainable checks
  • Organize tests: happy path first, then alternatives, then error conditions
  • Extract helpers for common test data and mock setup to avoid duplication
  • Refactor methods with >5–7 required tests into smaller units before testing heavily
  • Aim for meaningful coverage (target ~80%) and prioritize business-critical paths

Example use cases

  • Add a new REST endpoint: write @WebMvcTest with MockMvcTester and AssertJ assertions for response body and status
  • Fix a complex service method: suggest extraction points, then unit-test extracted units with JUnit 6 and Mockito
  • Validate repository behavior: run @DataJpaTest backed by Testcontainers PostgreSQL for real query verification
  • Migrate HTTP client tests: replace TestRestTemplate with RestTestClient and use @RestClientTest with a mock server
  • Verify JSON mapping changes: use @JsonTest to assert serialization/deserialization shape

FAQ

How do I choose between slice tests and @SpringBootTest?

Choose the smallest slice that fully assesses the behavior you care about; use @SpringBootTest only when interactions across many layers are required.

When should I use Testcontainers?

Use Testcontainers when repository or integration behavior depends on real database features, SQL compatibility, or realistic transactions that mocks cannot replicate.

What replaces @MockBean in Spring Boot 4?

Use @MockitoBean to mock Spring-managed dependencies in test slices; prefer narrow scope mocks rather than replacing whole contexts.