Overview
The Blackjack API project follows a comprehensive testing strategy that mirrors the hexagonal architecture. Tests are organized into three main layers: Domain, Application, and Infrastructure. This approach ensures that business logic is thoroughly tested independently of external dependencies.Testing Stack
- JUnit 5 - Testing framework
- Mockito - Mocking framework for unit tests
- Reactor Test - Testing reactive streams with
StepVerifier - Spring WebFlux Test -
WebTestClientfor controller integration tests
Running Tests
Run all tests using Maven:Test Organization
Tests are structured to match the application architecture:Domain Layer Tests
Domain tests are pure unit tests with no framework dependencies. They verify core business logic including game rules, card calculations, and domain model behavior.Example: Game Logic Test
Example: Hand Calculation Test
Domain Test Coverage
Domain tests cover:- ✅ Game creation and initialization
- ✅ Natural blackjack scenarios
- ✅ Player and dealer bust conditions
- ✅ Dealer hit/stand logic (dealer hits until 17+)
- ✅ Hand score calculations with Ace handling
- ✅ Invalid move prevention
- ✅ Value object validation
Application Layer Tests
Application layer tests verify use case workflows using Mockito to mock repository ports. These tests use Reactor Test’s StepVerifier for reactive stream validation.Example: Use Case Test
Application Test Coverage
Use case tests include:- ✅
CreateNewGameUseCase- Game creation and player initialization - ✅
GetGameStateUseCase- Game state retrieval - ✅
PlayMoveUseCase- HIT and STAND move execution - ✅
DeleteGameUseCase- Game deletion - ✅
ChangePlayerNameUseCase- Player name updates - ✅
ViewRankingUseCase- Player ranking calculations
Infrastructure Layer Tests
Infrastructure tests verify REST endpoints and HTTP integration using WebTestClient. These tests mock use cases and validate request/response handling.Example: Controller Test
Example: Error Handling Test
Infrastructure Test Coverage
Controller tests validate:- ✅ HTTP status codes (200, 201, 204, 400, 404, 409)
- ✅ Request/response JSON mapping
- ✅ Validation error handling
- ✅ Domain exception mapping via
GlobalExceptionHandler - ✅ Dealer card hiding logic (second card hidden during gameplay)
- ✅ Complete game state serialization
Test Coverage by Controller
GameController Tests
- POST
/game/new- Game creation - GET
/game/{id}- Game state retrieval - POST
/game/{id}/play- HIT and STAND moves - DELETE
/game/{id}/delete- Game deletion
PlayerController Tests
- PUT
/player/{playerId}- Player name changes
RankingController Tests
- GET
/ranking- Player ranking retrieval
Testing Best Practices
Domain Layer
Domain Layer
- Pure unit tests with no Spring framework dependencies
- Test business rules exhaustively
- Use domain-specific test data builders
- Verify invariants and preconditions
Application Layer
Application Layer
- Mock repository ports using Mockito
- Use StepVerifier for reactive stream testing
- Verify repository interactions with
verify() - Test both success and failure scenarios
Infrastructure Layer
Infrastructure Layer
- Use
@WebFluxTestfor controller slicing - Import
GlobalExceptionHandlerfor error handling tests - Mock use cases, not repositories
- Validate HTTP semantics (status codes, headers)
- Test JSON serialization/deserialization
Reactive Testing with StepVerifier
The project uses Reactor Test to verify reactive streams:Continuous Testing
Tests are automatically run on:- Local development via
./mvnw test - CI/CD pipelines (if configured)
- Pre-commit hooks (if configured)
Test Data Management
Tests use in-memory test data rather than external databases:- Domain tests use pure Java objects
- Application tests use Mockito mocks
- Infrastructure tests use mocked use cases
- ⚡ Fast test execution
- 🔒 Test isolation
- 🔄 No side effects between tests
Next Steps
Contributing Guide
Learn about development workflow and coding standards
Architecture
Understand the hexagonal architecture