Problem
The three existing test files mock everything at or above the service layer. Repository<T> and PlayerRepository have zero test coverage — the service tests verify that repository methods are called, never that they work. Several non-trivial behaviors are untested:
| Method |
Untested behavior |
GetAllAsync() |
AsNoTracking() — correctness concern for read performance |
FindByIdAsync() |
Returns null for a missing entity |
RemoveAsync() |
Null guard (if (entity != null)) — neither branch is exercised |
FindBySquadNumberAsync() |
Real FirstOrDefaultAsync query against the DB |
SquadNumberExistsAsync() |
Real AnyAsync query — on the critical path for the 409 Conflict response on POST, never tested against an actual database |
Proposed Solution
Add a PlayerRepositoryTests class covering the non-trivial behaviors using DatabaseFakes.MigrateAsync() on in-memory SQLite (already available after #459). Scope tightly — test behaviors that have real logic, not boilerplate EF Core delegation.
Roughly 8–10 tests:
GetAllAsync — returns all seeded players
FindByIdAsync — found (existing player) and not found (unknown ID)
RemoveAsync — entity found (removes it) and entity not found (no-op, no exception)
FindBySquadNumberAsync — found and not found
SquadNumberExistsAsync — exists and does not exist
Suggested Approach
- Create
test/.../Integration/ subfolder to distinguish from pure unit tests.
- Add
PlayerRepositoryTests.cs using DatabaseFakes.MigrateAsync() for setup — this also validates the full migration chain as a side effect.
- Use
[Trait("Category", "Integration")] on all tests in this class.
- Follow the service/validator naming convention:
{MethodName}_{StateUnderTest}_{ExpectedBehavior}.
- Use
PlayerData.MakeStarting11WithId() or PlayerFakes for known entities; use Guid.NewGuid() for unknown IDs.
Acceptance Criteria
Notes
References
Problem
The three existing test files mock everything at or above the service layer.
Repository<T>andPlayerRepositoryhave zero test coverage — the service tests verify that repository methods are called, never that they work. Several non-trivial behaviors are untested:GetAllAsync()AsNoTracking()— correctness concern for read performanceFindByIdAsync()nullfor a missing entityRemoveAsync()if (entity != null)) — neither branch is exercisedFindBySquadNumberAsync()FirstOrDefaultAsyncquery against the DBSquadNumberExistsAsync()AnyAsyncquery — on the critical path for the409 Conflictresponse on POST, never tested against an actual databaseProposed Solution
Add a
PlayerRepositoryTestsclass covering the non-trivial behaviors usingDatabaseFakes.MigrateAsync()on in-memory SQLite (already available after #459). Scope tightly — test behaviors that have real logic, not boilerplate EF Core delegation.Roughly 8–10 tests:
GetAllAsync— returns all seeded playersFindByIdAsync— found (existing player) and not found (unknown ID)RemoveAsync— entity found (removes it) and entity not found (no-op, no exception)FindBySquadNumberAsync— found and not foundSquadNumberExistsAsync— exists and does not existSuggested Approach
test/.../Integration/subfolder to distinguish from pure unit tests.PlayerRepositoryTests.csusingDatabaseFakes.MigrateAsync()for setup — this also validates the full migration chain as a side effect.[Trait("Category", "Integration")]on all tests in this class.{MethodName}_{StateUnderTest}_{ExpectedBehavior}.PlayerData.MakeStarting11WithId()orPlayerFakesfor known entities; useGuid.NewGuid()for unknown IDs.Acceptance Criteria
test/.../Integration/PlayerRepositoryTests.csexistsRepository<T>andPlayerRepositorywith non-trivial logic are coveredRemoveAsyncare testedSquadNumberExistsAsyncare testedDatabaseFakes.MigrateAsync()— no manual schema creation or seeding[Trait("Category", "Integration")]applied to all tests in the classCHANGELOG.mdupdatedNotes
Testcontainersfor Integration Testing with Database Containers #353 (Testcontainers): get the repository test suite right with in-memory SQLite first, then Testcontainers promotes the same tests to run against a real provider without rewriting them.Testcontainersfor Integration Testing with Database Containers #353) is the right longer-term answer for PostgreSQL provider parity (Add PostgreSQL support as configurable database provider #249).References
src/.../Repositories/Repository.cs— generic base withAddAsync,GetAllAsync,FindByIdAsync,UpdateAsync,RemoveAsyncsrc/.../Repositories/PlayerRepository.cs—FindBySquadNumberAsync,SquadNumberExistsAsynctest/.../Utilities/DatabaseFakes.cs—CreateSqliteConnection(),MigrateAsync()MigrateAsync()at startup — providesDatabaseFakes.MigrateAsync())Testcontainersfor Integration Testing with Database Containers #353 (Testcontainers)