Testing
These are the principles and templates I follow when writing test code.
Test Strategy
All Layer Testing (Required)
All layers of the architecture must be tested. Below is an example of testing in a Controller-Service-Repository 3-layer structure:
┌─────────────────────┐
│ Controller Test │ ← HTTP request/response testing
├─────────────────────┤
│ Service Test │ ← Business logic testing
├─────────────────────┤
│ Repository Test │ ← Database testing
└─────────────────────┘Core Principles:
- Controller: Test HTTP layer only, Mock Service
- Service: Test business logic only, Mock Repository
- Repository: Use actual database (or TestContainer)
Given-When-Then Pattern (Required)
All tests must include Given-When-Then comments:
| |
Controller Tests
Basic Template
| |
Controller Test Checklist
- Is Service mocked?
- Testing only HTTP request/response?
- Testing all HTTP status codes? (200, 201, 400, 404, etc.)
- Testing validation errors?
- Are Given-When-Then comments present?
Service Tests
Basic Template
| |
Service Test Checklist
- Is Repository mocked?
- Testing only business logic?
- Testing both success and failure cases?
- Testing exception handling?
- Using verify() to check invocations?
- Are Given-When-Then comments present?
Repository Tests
Basic Template
| |
Repository Test Checklist
- Using actual database or TestContainer?
- Using @DataJpaTest annotation?
- Initializing data in @BeforeEach?
- Testing all CRUD operations (Create, Read, Update, Delete)?
- Testing Soft Delete handling?
- Are Given-When-Then comments present?
Integration Tests
Spring MVC Integration Test
| |
Test Naming Convention
Recommended Format
| |
Security Testing
Authentication/Authorization Tests
All security-related endpoints must be tested.
| |
SQL Injection Prevention Tests
| |
XSS Prevention Tests
| |
Sensitive Data Protection Tests
| |
Concurrency Testing
Optimistic Locking Tests
| |
Pessimistic Locking Tests
| |
Multi-threaded Concurrency Tests
| |
Performance Testing
N+1 Query Verification
| |
Pagination Performance Tests
| |
Batch Processing Tests
| |
Advanced Integration Test Patterns
Transaction Rollback Pattern
| |
When to Use @DirtiesContext
| |
TestContainers Usage
| |
Database Initialization Strategies
| |
Test Data Management
Fixture Pattern
| |
Test Isolation
| |
Checklist
Common to all tests:
- Are Given-When-Then comments clearly written?
- Is the test name clear? (descriptive)
- Does one test verify only one case?
- Testing both success and failure cases?
Layer-specific tests:
- Controller test: Is Service mocked?
- Service test: Is Repository mocked?
- Repository test: Using actual DB or TestContainer?
Verification:
- Are results clearly verified with assertThat()?
- Is Mock invocation checked with verify()?
- Are exception cases tested?
Security Testing:
- Unauthenticated request tests (401) written?
- Unauthorized access tests (403) written?
- SQL Injection prevention verified?
- XSS prevention tested?
- Sensitive data not exposed in logs/responses verified?
Concurrency Testing:
- Optimistic Locking tests written?
- Pessimistic Locking tested when needed?
- Race Condition verified in multi-threaded environment?
- Critical business logic concurrency tested (e.g., stock decrease)?
Performance Testing:
- N+1 query problem verified?
- Fetch Join used appropriately?
- Pagination performance tested?
- Flush/clear used in batch processing?
Integration Testing:
- Test isolation guaranteed with @Transactional?
- TestContainers used for realistic environment testing?
- Test order independence guaranteed?
- @DirtiesContext not overused?
Test Data Management:
- Fixture pattern used for test data reuse?
- Builder or Object Mother pattern utilized?
- @BeforeEach and @BeforeAll used appropriately?
- Data isolation between tests guaranteed?