Commit all scripts
Some checks failed
Code Coverage / Generate Coverage Report (push) Has been cancelled
Tests / Run Tests (9.0.x) (push) Has been cancelled
Tests / Docker Build Test (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled

This commit is contained in:
Yaojia Wang
2025-11-03 17:19:20 +01:00
parent ebdd4ee0d7
commit 4183b10b39
24 changed files with 4917 additions and 11 deletions

View File

@@ -0,0 +1,403 @@
# ColaFlow Identity Module - Integration Tests
Professional .NET Integration Test project for Day 5 Refresh Token and RBAC functionality.
## Project Overview
This test project provides comprehensive integration testing for:
- **Phase 1**: Refresh Token functionality (token refresh, rotation, revocation)
- **Phase 2**: Role-Based Access Control (RBAC) (role assignment, JWT claims, role persistence)
- **Day 4 Regression**: Authentication basics (registration, login, password hashing)
## Project Structure
```
ColaFlow.Modules.Identity.IntegrationTests/
├── Infrastructure/
│ ├── ColaFlowWebApplicationFactory.cs # Custom WebApplicationFactory
│ ├── DatabaseFixture.cs # In-Memory database fixture
│ ├── RealDatabaseFixture.cs # PostgreSQL database fixture
│ └── TestAuthHelper.cs # Authentication test utilities
├── Identity/
│ ├── AuthenticationTests.cs # Day 4 regression tests
│ ├── RefreshTokenTests.cs # Day 5 Phase 1 tests
│ └── RbacTests.cs # Day 5 Phase 2 tests
├── appsettings.Testing.json # Test configuration
└── ColaFlow.Modules.Identity.IntegrationTests.csproj
```
## Test Categories
### 1. Authentication Tests (Day 4 Regression)
- RegisterTenant with valid/invalid data
- Login with correct/incorrect credentials
- Protected endpoint access with/without token
- JWT token claims validation
- Password hashing verification
- Complete auth flow (register → login → access)
**Total Tests**: 10
### 2. Refresh Token Tests (Day 5 Phase 1)
- RegisterTenant returns access + refresh tokens
- Login returns access + refresh tokens
- RefreshToken returns new token pair
- Old refresh token cannot be reused (token rotation)
- Invalid refresh token fails
- Logout revokes refresh token
- Refresh token maintains user identity
- Multiple refresh operations work
- Expired refresh token fails
**Total Tests**: 9
### 3. RBAC Tests (Day 5 Phase 2)
- RegisterTenant assigns TenantOwner role
- JWT contains role claims
- Login preserves role
- RefreshToken preserves role
- /api/auth/me returns user role
- JWT contains all required role claims
- Multiple token refresh maintains role
- Protected endpoint access with valid role succeeds
- Protected endpoint access without token fails
- Protected endpoint access with invalid token fails
- Role consistency across all authentication flows
**Total Tests**: 11
**Grand Total**: **30 Integration Tests**
## Test Infrastructure
### WebApplicationFactory
The `ColaFlowWebApplicationFactory` supports two database modes:
#### 1. In-Memory Database (Default)
- Fast, isolated tests
- No external dependencies
- Each test class gets its own database instance
- **Recommended for CI/CD pipelines**
```csharp
var factory = new ColaFlowWebApplicationFactory(useInMemoryDatabase: true);
```
#### 2. Real PostgreSQL Database
- Tests actual database behavior
- Verifies migrations and real database constraints
- Requires PostgreSQL running on localhost
- **Recommended for local testing**
```csharp
var factory = new ColaFlowWebApplicationFactory(useInMemoryDatabase: false);
```
### Database Fixtures
#### DatabaseFixture (In-Memory)
- Implements `IClassFixture<DatabaseFixture>`
- Provides isolated database per test class
- Automatic cleanup after tests
#### RealDatabaseFixture (PostgreSQL)
- Implements `IClassFixture<RealDatabaseFixture>`
- Creates unique test database per test run
- Automatic cleanup (database deletion) after tests
## NuGet Packages
| Package | Version | Purpose |
|---------|---------|---------|
| `xunit` | 2.9.2 | Test framework |
| `xunit.runner.visualstudio` | 2.8.2 | Visual Studio test runner |
| `Microsoft.AspNetCore.Mvc.Testing` | 9.0.0 | WebApplicationFactory |
| `Microsoft.EntityFrameworkCore.InMemory` | 9.0.0 | In-Memory database |
| `Npgsql.EntityFrameworkCore.PostgreSQL` | 9.0.4 | PostgreSQL provider |
| `FluentAssertions` | 7.0.0 | Fluent assertion library |
| `System.IdentityModel.Tokens.Jwt` | 8.14.0 | JWT token parsing |
## Running Tests
### Prerequisites
**For In-Memory Tests** (No external dependencies):
- .NET 9.0 SDK installed
**For PostgreSQL Tests**:
- PostgreSQL running on `localhost:5432`
- Username: `postgres`
- Password: `postgres`
- Database: `colaflow_test` (auto-created)
### Command Line
#### Run All Tests
```bash
cd c:\Users\yaoji\git\ColaCoder\product-master\colaflow-api
dotnet test tests/Modules/Identity/ColaFlow.Modules.Identity.IntegrationTests
```
#### Run Specific Test Class
```bash
# Refresh Token Tests only
dotnet test --filter "FullyQualifiedName~RefreshTokenTests"
# RBAC Tests only
dotnet test --filter "FullyQualifiedName~RbacTests"
# Authentication Tests only
dotnet test --filter "FullyQualifiedName~AuthenticationTests"
```
#### Run Specific Test Method
```bash
dotnet test --filter "FullyQualifiedName~RefreshToken_ShouldReturnNewTokenPair"
```
#### Verbose Output
```bash
dotnet test --logger "console;verbosity=detailed"
```
#### Generate Coverage Report
```bash
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=lcov /p:CoverletOutput=./coverage.lcov
```
### Visual Studio / Rider
1. **Visual Studio**:
- Open Test Explorer (Test → Test Explorer)
- Right-click project → Run Tests
- Or right-click individual test → Run Test
2. **JetBrains Rider**:
- Open Unit Tests window (View → Tool Windows → Unit Tests)
- Right-click project → Run Unit Tests
- Or use `Ctrl+U, Ctrl+R` shortcut
### Parallel Execution
By default, xUnit runs test classes in parallel but tests within a class sequentially. This is perfect for integration tests because:
- Each test class uses its own `DatabaseFixture` (isolated database)
- Tests within a class share the same database (sequential execution prevents conflicts)
To disable parallelization (for debugging):
```csharp
[assembly: CollectionBehavior(DisableTestParallelization = true)]
```
## Test Configuration
### appsettings.Testing.json
```json
{
"ConnectionStrings": {
"IdentityConnection": "Host=localhost;Port=5432;Database=colaflow_test;Username=postgres;Password=postgres"
},
"Jwt": {
"SecretKey": "test-secret-key-min-32-characters-long-12345678901234567890",
"Issuer": "ColaFlow.API.Test",
"Audience": "ColaFlow.Web.Test",
"ExpirationMinutes": "15",
"RefreshTokenExpirationDays": "7"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
}
}
```
### Override Configuration
You can override configuration in tests:
```csharp
builder.ConfigureAppConfiguration((context, config) =>
{
config.AddInMemoryCollection(new Dictionary<string, string>
{
["Jwt:ExpirationMinutes"] = "5",
["Jwt:RefreshTokenExpirationDays"] = "1"
});
});
```
## Test Helpers
### TestAuthHelper
Provides convenient methods for common test scenarios:
```csharp
// Register and get tokens
var (accessToken, refreshToken) = await TestAuthHelper.RegisterAndGetTokensAsync(client);
// Login and get tokens
var (accessToken, refreshToken) = await TestAuthHelper.LoginAndGetTokensAsync(
client, "tenant-slug", "email@test.com", "password");
// Parse JWT token
var claims = TestAuthHelper.ParseJwtToken(accessToken);
// Get specific claim
var userId = TestAuthHelper.GetClaimValue(accessToken, "user_id");
// Check role
bool isOwner = TestAuthHelper.HasRole(accessToken, "TenantOwner");
```
## CI/CD Integration
### GitHub Actions
```yaml
name: Integration Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 9.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore
- name: Run Integration Tests
run: dotnet test tests/Modules/Identity/ColaFlow.Modules.Identity.IntegrationTests --no-build --verbosity normal
```
### Azure DevOps
```yaml
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UseDotNet@2
inputs:
version: '9.0.x'
- task: DotNetCoreCLI@2
displayName: 'Restore'
inputs:
command: 'restore'
- task: DotNetCoreCLI@2
displayName: 'Build'
inputs:
command: 'build'
- task: DotNetCoreCLI@2
displayName: 'Test'
inputs:
command: 'test'
projects: '**/ColaFlow.Modules.Identity.IntegrationTests.csproj'
```
## Test Coverage Goals
- **Line Coverage**: ≥ 80%
- **Branch Coverage**: ≥ 70%
- **Critical Paths**: 100% coverage for:
- Token generation and refresh
- Role assignment and persistence
- Authentication flows
## Troubleshooting
### Test Failures
#### "Database connection failed"
- Ensure PostgreSQL is running (`RealDatabaseFixture` only)
- Check connection string in `appsettings.Testing.json`
- Use In-Memory database for tests that don't need real database
#### "Token validation failed"
- Verify `Jwt:SecretKey` matches between test config and API config
- Check token expiration time is sufficient
- Ensure clock skew tolerance is configured
#### "Test isolation issues"
- Ensure each test class uses `IClassFixture<DatabaseFixture>`
- Verify tests don't share global state
- Use unique tenant slugs and emails (`Guid.NewGuid()`)
#### "Port already in use"
- The test server uses a random port by default
- No need to stop the real API server
- If issues persist, use `_factory.Server` instead of `_factory.CreateClient()`
### Debug Tips
#### Enable Detailed Logging
```csharp
builder.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Debug);
});
```
#### Inspect Database State
```csharp
using var scope = Factory.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<IdentityDbContext>();
var users = db.Users.ToList();
// Inspect users...
```
#### Pause Test Execution
```csharp
await Task.Delay(TimeSpan.FromSeconds(30)); // Inspect state manually
```
## Best Practices
1. **Use In-Memory Database for most tests**: Faster, no dependencies
2. **Use Real Database for critical paths**: Migrations, constraints, transactions
3. **Isolate tests**: Each test should be independent
4. **Use unique identifiers**: `Guid.NewGuid()` for slugs, emails
5. **Clean up after tests**: Use `IDisposable` fixtures
6. **Use FluentAssertions**: More readable assertions
7. **Test happy paths AND error cases**: Both success and failure scenarios
8. **Use descriptive test names**: `MethodName_Scenario_ExpectedResult`
## Future Enhancements
- [ ] Add Testcontainers for PostgreSQL (no manual setup required)
- [ ] Add performance benchmarks
- [ ] Add load testing (k6 integration)
- [ ] Add Swagger/OpenAPI contract tests
- [ ] Add mutation testing (Stryker.NET)
- [ ] Add E2E tests with Playwright
## Contributing
When adding new tests:
1. Follow existing test structure and naming conventions
2. Use `TestAuthHelper` for common operations
3. Ensure tests are isolated and don't depend on execution order
4. Add test documentation in this README
5. Verify tests pass with both In-Memory and Real database
## License
This test project is part of ColaFlow and follows the same license.
---
**Questions?** Contact the QA team or refer to the main ColaFlow documentation.