Backend Testing Strategy
Relevant source files
The following files were used as context for generating this wiki page:
- REVIEW.md
- package.json
- packages/api.tests/Users/UserServiceTests.cs
- packages/api.tests/Customers/CustomerServiceTests.cs
- packages/api.tests.integration/Customers/CustomerEndpointsTests.cs
- packages/api.tests.integration/Users/UserEndpointsTests.cs
- packages/api.tests.integration/Contracts/ContractEndpointsTests.cs
- packages/api.tests/Common/Filters/ValidationFilterTests.cs
The Backend Testing Strategy for the tsz project focuses on a multi-layered approach to ensure the reliability of the .NET API. It encompasses isolated unit testing of business logic within services and end-to-end integration testing of API endpoints. The strategy emphasizes validating CRUD operations, pagination, search functionality, and complex business constraints such as duplicate email prevention and sequential number generation.
Sources: REVIEW.md, packages/api.tests/Users/UserServiceTests.cs, packages/api.tests.integration/Customers/CustomerEndpointsTests.cs
Testing Architecture
The project utilizes xUnit as the primary testing framework. Tests are categorized into two main projects within the packages directory: api.tests (Unit/Service Tests) and api.tests.integration (Integration/Endpoint Tests).
Service Level Testing (Unit)
Service tests target the business logic layer. They utilize Microsoft.EntityFrameworkCore.InMemory to simulate the database environment, allowing for fast execution without external dependencies.
- Data Seeding: Tests often include helper methods like
AddUserAsyncorAddCustomerAsyncto populate the in-memory database before execution. - Dependency Injection: Services are instantiated manually in a
CreateServicehelper method, which also configures theAppDbContextwith a unique database name per test to ensure isolation.
Sources: packages/api.tests/Users/UserServiceTests.cs:10-30, packages/api.tests/Customers/CustomerServiceTests.cs:12-25
Endpoint Level Testing (Integration)
Integration tests verify the full HTTP request/response pipeline. They use a custom TestApiFactory to host the API in-memory.
- Fixture Usage: Classes implement
IClassFixture<TFactory>andIAsyncLifetimeto manage the lifecycle of the test server and database state. - HTTP Client: A specialized
HttpClientis used to send JSON requests to the API and assert on status codes and response bodies.
Sources: packages/api.tests.integration/Customers/CustomerEndpointsTests.cs:13-40, packages/api.tests.integration/Users/UserEndpointsTests.cs:13-35
Test Categories and Patterns
| Category | Target | Description |
|---|---|---|
| Unit Tests | UserService, CustomerService | Validates logic for sorting, pagination, search filtering, and archival state. |
| Integration Tests | REST Endpoints (/api/users, /api/customers) | Validates HTTP status codes (200 OK, 201 Created, 404 Not Found, 409 Conflict). |
| Validation Tests | ValidationFilter | Ensures that System.ComponentModel.DataAnnotations are correctly enforced by the middleware. |
| Business Rules | Sequential IDs, Constraints | Tests that CounterService correctly increments numbers and unique constraints prevent duplicates. |
Sources: packages/api.tests/Common/Filters/ValidationFilterTests.cs, packages/api.tests.integration/Contracts/ContractEndpointsTests.cs, packages/api.tests/Users/UserServiceTests.cs
Sequential Number Generation Flow
The following diagram illustrates how the testing strategy validates sequential number generation for entities like Contracts and Customers.
The testing suite ensures that the CounterService maintains state across requests and prevents collisions.
Sources: packages/api.tests.integration/Customers/CustomerEndpointsTests.cs:72-78, packages/api.tests/Contracts/ContractServiceTests.cs:101-112
Execution and Automation
The project provides standardized scripts in the root package.json to execute the test suite using the dotnet test CLI.
| Command | Action |
|---|---|
bun run test:api | Executes unit tests in packages/api.tests. |
bun run test:api:int | Executes integration tests in packages/api.tests.integration. |
bun run test:all | Runs all web tests and the full .NET solution tests. |
Sources: package.json:13-16
Implementation Details
Validation Filter Testing
Tests for the ValidationFilter<T> verify that invalid models are caught before reaching the service layer, returning a ProblemHttpResult.
[Fact]
public async Task InvokeAsync_InvalidModel_ReturnsValidationProblem()
{
var filter = new ValidationFilter<TestModel>();
var model = new TestModel { Name = null, Age = 30 }; // Name is [Required]
var context = CreateContext(model);
var result = await filter.InvokeAsync(context, Next);
var problem = Assert.IsType<ProblemHttpResult>(result);
var details = Assert.IsType<HttpValidationProblemDetails>(problem.ProblemDetails);
Assert.True(details.Errors.ContainsKey(nameof(TestModel.Name)));
}
Sources: packages/api.tests/Common/Filters/ValidationFilterTests.cs:64-77
Integration Test Setup
The following sequence diagram shows the initialization and execution flow of an integration test for creating a user.
Sources: packages/api.tests.integration/Users/UserEndpointsTests.cs:55-66, packages/api.tests.integration/Common/TestApiFactory.cs (referenced by type)
Conclusion
The backend testing strategy ensures that every module (Users, Customers, Contracts, LeaveTypes) is validated at both the logic and interface levels. By utilizing in-memory databases and isolated test factories, the suite remains performant while providing high confidence in the application's business rules and API stability.
Sources: REVIEW.md, packages/api.tests/Users/UserServiceTests.cs