Testing
SkillDatabases & dataOnce added, this skill lets your AI write and run tests for EF Core the way the project expects. It covers how the test setup works, including fixtures, SQL baseline assertions, test helpers, and the test class hierarchy. It is useful when adding new tests or changing existing ones.
Available today. Use it from your connected AI after setup.
No other account needed.
After adding it, ask your AI to add a new test or change an existing one in the EF Core project. It will follow the project's established patterns for fixtures, assertions, and helpers.
Then ask your AI: use the Testing skill
What your AI can do with it
- Write new EF Core tests
- Run EF Core tests
- Update test fixtures
- Adjust SQL baseline assertions
- Create or modify test helpers
- Make changes to the test class hierarchy
What this skill tells your AI
The instructions your AI receives, as published by dotnet/efcore in .agents/skills/testing/SKILL.md and read by ahel’s review.
Test Categories
Unit Tests (test/EFCore.Tests/, test/EFCore.Relational.Tests/, test/EFCore.{Provider}.Tests/)
Isolated logic tests. Build models via *TestHelpers.Instance.CreateConventionBuilder(), resolve services from CreateContextServices(). No database needed.
Specification Tests (provider-agnostic abstract bases)
Define WHAT to test (LINQ queries, expected results). Can't be run directly — provider tests override to verify HOW (generated SQL).
- Core →
test/EFCore.Specification.Tests/ - Relational →
test/EFCore.Relational.Specification.Tests/
Functional Tests (test/EFCore.{Provider}.FunctionalTests/)
Concrete provider tests inheriting specification tests. Most include SQL baseline assertions.
Test Class Hierarchy (Query Example)
QueryTestBase<TFixture> # Core
└─ NorthwindWhereQueryTestBase<TFixture> # Specification
└─ NorthwindWhereQueryRelationalTestBase<TFixture> # Relational specification
└─ NorthwindWhereQuerySqlServerTest # Provider (asserts SQL)
Provider override pattern:
public override async Task Where_simple(bool async)
{
await base.Where_simple(async); // runs LINQ + asserts results
AssertSql("""..."""); // asserts provider-specific SQL
}
TestHelpers Hierarchy
TestHelpers (abstract) # EFCore.Specification.Tests
├─ InMemoryTestHelpers # non-relational
└─ RelationalTestHelpers (abstract) # EFCore.Relational.Specification.Tests
├─ SqlServerTestHelpers
└─ SqliteTestHelpers
Key methods: CreateConventionBuilder(), CreateContextServices(model), CreateOptions()
Fixtures
SharedStoreFixtureBase
Many tests share one database. Creates TestStore + pooled DbContextFactory in InitializeAsync(). Seeds data once. Use for read-heavy tests (e.g., Northwind query tests).
NonSharedModelTestBase
Each test gets a fresh model/store. Call InitializeAsync<TContext>(onModelCreating, seed, ...) per test. Use for tests needing unique schemas.
SQL Baseline Assertions
TestSqlLoggerFactory captures SQL. AssertSql("""...""") compares against expected. Set EF_TEST_REWRITE_BASELINES=1 to auto-rewrite baselines via Roslyn.
Workflow: Adding New Tests
- Specification test: Add to
EFCore.Specification.Tests(core) orEFCore.Relational.Specification.Tests(relational) - Provider overrides: Override in every provider functional test class (
EFCore.{Provider}.FunctionalTests) that inherits the base with provider-appropriate assertions. - Unit test: Add to
EFCore.{Provider}.Tests - Run with
EF_TEST_REWRITE_BASELINES=1to capture initial baselines - Run tests with project rebuilding enabled (don't use
--no-build) to ensure code changes are picked up - When testing cross-platform code (e.g., file paths, path separators), verify the fix works on both Windows and Linux/macOS
Common Pitfalls
| Pitfall | Solution |
|---|---|
| Baseline mismatch (SQL or compiled model) | Re-run with EF_TEST_REWRITE_BASELINES=1 |
Check_all_tests_overridden fails | Override the new test in every inheriting provider class |
| SQL Server feature missing at lower compat level | Gate with [SqlServerCondition(...)] |
Running Tests Directly Against the Built Assembly
When invoking the test DLL via dotnet exec (e.g. to isolate a single test method without rebuilding through dotnet test), always append --filter-not-trait category=failing --ignore-exit-code 8:
dotnet exec ./Microsoft.EntityFrameworkCore.SqlServer.FunctionalTests.dll `
--filter-method '*MigrationsSqlServerTest.Create_json_index_over_whole_complex_collection' `
--filter-not-trait category=failing --ignore-exit-code 8
These flags mirror what test/Directory.Build.props passes via TestingPlatformCommandLineArguments.
Don't add --no-build unless the test assembly was built in the immediate previous step.
Signals
- GitHub stars
- 15k
- Forks
- 3k
- Last commit
- Sep 2026
- Hacker News mentions
- 20
Advanced
- Catalog kind
- skill
- Gateway key
testing-dotnet- Source
- github.com/dotnet/efcore