Spring Boot TDD with Mockito
TDD Cycle: Red → Green → Refactor
code
┌─────────────────────────────────────────────────────────────┐ │ TDD WORKFLOW │ │ │ │ ┌───────┐ ┌───────┐ ┌──────────┐ │ │ │ RED │ ───→ │ GREEN │ ───→ │ REFACTOR │ ───┐ │ │ │ │ │ │ │ │ │ │ │ │ Write │ │ Write │ │ Improve │ │ │ │ │ Test │ │ Code │ │ Code │ │ │ │ └───────┘ └───────┘ └──────────┘ │ │ │ ↑ │ │ │ └──────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘
Mockito Annotations
| Annotation | Purpose |
|---|---|
@Mock | Create mock object |
@InjectMocks | Inject mocks into class under test |
@Spy | Partial mock - real methods + mock behavior |
@Captor | Capture arguments passed to mock |
@MockBean | Mock bean in Spring context |
Test Template
java
@ExtendWith(MockitoExtension.class)
class ServiceTest {
@Mock
private Repository repository;
@InjectMocks
private Service service;
@Test
@DisplayName("Should do something when condition is met")
void shouldDoSomethingWhenConditionIsMet() {
// Given (Arrange)
when(repository.findById(1L)).thenReturn(Optional.of(entity));
// When (Act)
var result = service.doSomething(1L);
// Then (Assert)
assertThat(result).isNotNull();
verify(repository).findById(1L);
}
}
Best Practices
- •One assertion per test - Focus on single behavior
- •Descriptive test names - Use
@DisplayName - •AAA Pattern - Arrange, Act, Assert
- •Test behavior, not implementation
- •Fast tests - Mock external dependencies
- •Isolated tests - No shared state