mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 10:42:08 +00:00
6.7 KiB
6.7 KiB
Testing
This document describes the testing strategy and how to run tests for The Biergarten App.
Overview
The project uses a multi-layered testing approach:
- API.Specs - BDD integration tests using Reqnroll (Gherkin)
- Infrastructure.Repository.Tests - Unit tests for data access layer
- Service.Auth.Tests - Unit tests for authentication business logic
Running Tests with Docker (Recommended)
The easiest way to run all tests is using Docker Compose, which sets up an isolated test environment:
docker compose -f docker-compose.test.yaml up --abort-on-container-exit
This command:
- Starts a fresh SQL Server instance
- Runs database migrations
- Seeds test data
- Executes all test suites in parallel
- Exports results to
./test-results/ - Exits when tests complete
View Test Results
# List test result files
ls -la test-results/
# View specific test results
cat test-results/api-specs/results.trx
cat test-results/repository-tests/results.trx
cat test-results/service-auth-tests/results.trx
Clean Up
# Remove test containers and volumes
docker compose -f docker-compose.test.yaml down -v
Running Tests Locally
You can run individual test projects locally without Docker:
Integration Tests (API.Specs)
cd src/Core
dotnet test API/API.Specs/API.Specs.csproj
Requirements:
- SQL Server instance running
- Database migrated and seeded
- Environment variables set (DB connection, JWT secret)
Repository Tests
cd src/Core
dotnet test Infrastructure/Infrastructure.Repository.Tests/Infrastructure.Repository.Tests.csproj
Requirements:
- SQL Server instance running (uses mock data)
Service Tests
cd src/Core
dotnet test Service/Service.Auth.Tests/Service.Auth.Tests.csproj
Requirements:
- No database required (uses Moq for mocking)
Test Coverage
Current Coverage
Authentication & User Management:
- ✅ User registration with validation
- ✅ User login with JWT token generation
- ✅ Password hashing and verification (Argon2id)
- ✅ JWT token generation and claims
- ✅ Invalid credentials handling
- ✅ 404 error responses
Repository Layer:
- ✅ User account creation
- ✅ User credential management
- ✅ GetUserByUsername queries
- ✅ Stored procedure execution
Service Layer:
- ✅ Login service with password verification
- ✅ Register service with validation
- ✅ Business logic for authentication flow
Planned Coverage
- Email verification workflow
- Password reset functionality
- Token refresh mechanism
- Brewery data management
- Beer post operations
- User follow/unfollow
- Image upload service
Testing Frameworks & Tools
xUnit
- Primary unit testing framework
- Used for Repository and Service layer tests
- Supports parallel test execution
Reqnroll (Gherkin/BDD)
- Behavior-driven development framework
- Used for API integration tests
- Human-readable test scenarios in
.featurefiles
FluentAssertions
- Expressive assertion library
- Makes test assertions more readable
- Used across all test projects
Moq
- Mocking framework for .NET
- Used in Service layer tests
- Enables isolated unit testing
DbMocker
- Database mocking for repository tests
- Simulates SQL Server responses
- No real database required for unit tests
Test Structure
API.Specs (Integration Tests)
API.Specs/
├── Features/
│ ├── Authentication.feature # Login/register scenarios
│ └── UserManagement.feature # User CRUD scenarios
├── Steps/
│ ├── AuthenticationSteps.cs # Step definitions
│ └── UserManagementSteps.cs
└── Mocks/
└── TestApiFactory.cs # Test server setup
Example Feature:
Feature: User Authentication
As a user
I want to register and login
So that I can access the platform
Scenario: Successful user registration
Given I have valid registration details
When I register a new account
Then I should receive a JWT token
And my account should be created
Infrastructure.Repository.Tests
Infrastructure.Repository.Tests/
├── AuthRepositoryTests.cs # Auth repository tests
├── UserAccountRepositoryTests.cs # User account tests
└── TestFixtures/
└── DatabaseFixture.cs # Shared test setup
Service.Auth.Tests
Service.Auth.Tests/
├── LoginService.test.cs # Login business logic tests
└── RegisterService.test.cs # Registration business logic tests
Writing Tests
Unit Test Example (xUnit)
public class LoginServiceTests
{
[Fact]
public async Task LoginAsync_ValidCredentials_ReturnsToken()
{
// Arrange
var mockRepo = new Mock<IAuthRepository>();
var mockJwt = new Mock<IJwtService>();
var service = new AuthService(mockRepo.Object, mockJwt.Object);
// Act
var result = await service.LoginAsync("testuser", "password123");
// Assert
result.Should().NotBeNull();
result.Token.Should().NotBeNullOrEmpty();
}
}
Integration Test Example (Reqnroll)
Scenario: User login with valid credentials
Given a registered user with username "testuser"
When I POST to "/api/auth/login" with valid credentials
Then the response status should be 200
And the response should contain a JWT token
Continuous Integration
Tests run automatically in CI/CD pipelines using the test Docker Compose configuration:
# CI/CD command
docker compose -f docker-compose.test.yaml build
docker compose -f docker-compose.test.yaml up --abort-on-container-exit
docker compose -f docker-compose.test.yaml down -v
Exit codes:
0- All tests passed- Non-zero - Test failures occurred
Troubleshooting
Tests Failing Due to Database Connection
Ensure SQL Server is running and environment variables are set:
docker compose -f docker-compose.test.yaml ps
Port Conflicts
If port 1433 is in use, stop other SQL Server instances or modify the port in docker-compose.test.yaml.
Stale Test Data
Clean up test database:
docker compose -f docker-compose.test.yaml down -v
View Container Logs
docker compose -f docker-compose.test.yaml logs <service-name>
Best Practices
- Isolation: Each test should be independent and not rely on other tests
- Cleanup: Use fixtures and dispose patterns for resource cleanup
- Mocking: Mock external dependencies in unit tests
- Descriptive Names: Use clear, descriptive test method names
- Arrange-Act-Assert: Follow AAA pattern in unit tests
- Given-When-Then: Follow GWT pattern in BDD scenarios