-
Notifications
You must be signed in to change notification settings - Fork 226
Settings.AddUnitTestingDbContext
Generates an in-memory stand-in for the context, so unit tests can run without a database.
Settings.AddUnitTestingDbContext |
Settings.FakeDbContextInDebugOnlyMode |
|
| Type | bool |
bool |
| Default | true |
false |
In Database.tt? |
Yes | Yes |
AddUnitTestingDbContext generates FakeMyDbContext and FakeDbSet<T>. The fake implements the same
interface as the real context, backed by plain List<T> collections, so a class that depends on
IMyDbContext can be tested by handing it the fake.
FakeDbContextInDebugOnlyMode wraps those classes in #if DEBUG / #endif, so they are compiled out of a
Release build.
public interface IMyDbContext : IDisposable
public class MyDbContext : DbContext, IMyDbContext
public class MyDbContextFactory : IDesignTimeDbContextFactory<MyDbContext>
public class Category
public class Product
public class sales_Order
public class CategoryConfiguration : IEntityTypeConfiguration<Category>
public class ProductConfiguration : IEntityTypeConfiguration<Product>
public class sales_OrderConfiguration : IEntityTypeConfiguration<sales_Order>public interface IMyDbContext : IDisposable
public class MyDbContext : DbContext, IMyDbContext
public class MyDbContextFactory : IDesignTimeDbContextFactory<MyDbContext>
public class FakeMyDbContext : IMyDbContext
public class FakeDbSet<TEntity> :
public class FakeDbAsyncQueryProvider<TEntity> : FakeQueryProvider<TEntity>, IAsyncEnumerable<TEntity>, IAsyncQueryProvider
public class FakeDbAsyncEnumerable<T> : EnumerableQuery<T>, IAsyncEnumerable<T>, IQueryable<T>
public class FakeDbAsyncEnumerator<T> : IAsyncEnumerator<T>
public abstract class FakeQueryProvider<T> : IOrderedQueryable<T>, IQueryProvider
public class FakeExpressionVisitor : ExpressionVisitor
public class FakeDbContextShim : DbContext
public class FakeDatabaseFacade : DatabaseFacade, IDatabaseFacadeDependenciesAccessor, IInfrastructure<IServiceProvider>
public class FakeExecutionStrategy : IExecutionStrategy
public class FakeDbContextTransaction : IDbContextTransaction
public class Category
public class Product
public class sales_Order
public class CategoryConfiguration : IEntityTypeConfiguration<Category>
public class ProductConfiguration : IEntityTypeConfiguration<Product>
public class sales_OrderConfiguration : IEntityTypeConfiguration<sales_Order>[SetUp]
public void Setup()
{
_context = new FakeMyDbContext();
_context.Categories.Add(new Category { CategoryId = 1, CategoryName = "Tools" });
_repository = new CategoryRepository(_context);
}
[Test]
public void Count_returns_the_number_of_categories()
{
Assert.That(_repository.Count(), Is.EqualTo(1));
}Full worked example on FakeDbContext.
When the generated code ships in a package. Test scaffolding in a published library is dead weight for
every consumer. FakeDbContextInDebugOnlyMode = true is the middle ground - keep it for local test runs,
compile it out of the Release build.
When you test against SQLite in-memory instead, which many people prefer because it enforces relational constraints the fake cannot. See SQLite for that pattern.
When it doubles the size of a file you have to read. On a large model the fake context and its DbSets
are as long again as the real thing.
The fake is a list, not a database. It does not enforce foreign keys, uniqueness, NOT NULL or maximum
lengths; it does not apply defaults; it does not generate identity values; and SaveChanges() does nothing.
A test that passes against the fake can fail against the database for any of those reasons.
LINQ runs in memory, so it behaves differently. Queries against the fake use LINQ to Objects, where string
comparison is case-sensitive and DateTime arithmetic is .NET's. The same query against SQL Server uses
the database's collation and semantics. Tests that depend on either will disagree.
No lazy loading, no Include. Navigation properties are only populated if you populate them. Include
against the fake is a no-op rather than an error, which makes a missing-data bug look like a logic bug.
FakeDbContextInDebugOnlyMode does nothing unless AddUnitTestingDbContext is on. It only wraps classes
that are being generated.
If it is on and your test project builds in Release, the fake will not exist. That is the intended behaviour and it is still a confusing build error the first time.
- FakeDbContext - the full worked example, and how it compares to the in-memory provider
- SQLite - in-memory SQLite as a more faithful test double
-
Settings.ElementsToGenerate - the fake needs
Elements.Context - Settings Reference
- Settings A-Z - every setting, with a page each
- Common Settings Types Explained
- Settings Callbacks
- Settings runtime values and helpers
- Filtering
- Full Control Over the Generated Code
- Enum Generation from Table Data
- Owned Entities
- JSON column support
- Global Query Filters
- Extended Property Names Feature
- Partial Properties
- File-Scoped Namespaces
- Data Annotations
- Spatial Types
- HierarchyId
- RowVersion and TimeStamp columns
- Lazy Loading
- Stored proc result sets
- Custom File-Based Templates
- Extra entities via partial classes
- INotifyPropertyChanged
- Syntax colour for T4