Introduction
ShopNest repository tests need a database — EF InMemory is fast but lies about SQL behavior; SQLite in-memory runs real SQL and catches more bugs.
After this article you will
- Compare EF InMemory vs SQLite test providers
- Seed test data and test complex LINQ queries
- Choose fresh DbContext per test vs shared
- Test repository and specification implementations
- Reset databases with Respawn
Prerequisites
- Article 55 — Integration Testing
- ShopNest Order Service / API from prior modules
Concept deep-dive
| Provider | Pros | Cons |
|---|---|---|
| EF InMemory | Fastest, no SQL | No FK constraints, different semantics |
| SQLite memory | Real SQL, relational | Not 100% SQL Server identical |
| SQL Server LocalDB | Closest to prod | Slower, CI setup harder |
private ShopNestDbContext CreateContext()
{
var options = new DbContextOptionsBuilder<ShopNestDbContext>()
.UseSqlite("DataSource=:memory:")
.Options;
var ctx = new ShopNestDbContext(options);
ctx.Database.OpenConnection();
ctx.Database.EnsureCreated();
SeedTestProducts(ctx);
return ctx;
}
[Fact]
public async Task GetByRegion_ReturnsFilteredCustomers()
{
using var ctx = CreateContext();
var repo = new CustomerRepository(ctx);
var spec = new CustomersByRegionSpec("South");
var result = await repo.ListAsync(spec);
Assert.All(result, c => Assert.Equal("South", c.Region));
}
Hands-on — ShopNest Repository Layer Testing
- Repository tests with SQLite :memory: per test.
- Test Include/specification SQL-heavy queries.
- Document InMemory failures (Ignore FK) you hit once.
- Respawn reset for integration test SQL Server.
Common errors & best practices
- InMemory for testing transactions — not supported reliably.
- Shared context mutated across parallel tests — disable parallel or isolate.
- Assuming SQLite = SQL Server — test critical queries on real SQL in CI.
Interview questions
Q: Why not InMemory?
A: Ignores constraints and provider-specific SQL — SQLite closer to real.
Q: EnsureCreated vs Migrate?
A: EnsureCreated for tests; Migrate if testing migration scripts.
Summary
- Prefer SQLite in-memory over EF InMemory for repos
- Seed minimal data per test for clarity
- Test specifications against real LINQ-to-SQL
- Respawn cleans SQL Server between integration tests
Previous: Integration Testing
Next: Performance and Load Testing
FAQ
Test migrations?
Use Migrate() against LocalDB or Testcontainers SQL.
Parallel repo tests?
Unique database name per test collection.