TransientContext
is a simple tool for creating transient or disposable databases for integration
testing. During integration testing TransientContext
can be used to create a disposable database
from an existing schema and drop the database after tests are complete. TransientContext
supports
PostgreSQL and SQLite databases.
- Current Version:
1.2.0
- Target Framework:
.NET Standard 2.0
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.Sqlite
- Microsoft.Extensions.Configuration.Json
- Microsoft.Extensions.Configuration.UserSecrets
- Microsoft.NET.Test.Sdk
- Npgsql.EntityFrameworkCore.PostgreSQL
- Xunit
- Xunit.runner.visualstudio
- NUnit
- NUnit3TestAdapter
The examples below are taken directly from TransientContext.Tests.NUnit
and TransientContext.Tests.Xunit
. In
the PostgreSQL examples connection strings are stored in user secrets files as described in the Microsoft documentation.
-
Begin by creating a database fixture. In the example below,
DomainContext
represents theEntityFramework
DBContext
that is being created. For reference, seeTransientContext.Tests.NUnit/Common/Data/DomainContext.cs
.public class DatabaseFixture : IDisposable { public DatabaseFixture() { var configuration = new ConfigurationBuilder() .AddUserSecrets("your-secret-guid") .Build(); TestDatabase = new TestDatabaseBuilder() .WithConfiguration(configuration) .Build(); /* Or for SQLite * * TestDatabase = new TestDatabaseBuilder() * .WithConnectionString("Data Source=domain.db") * .Build(); */ TestDatabase.Create(); var builder = new DbContextOptionsBuilder<DomainContext>() .UseNpgsql(TestDatabase.ConnectionString); DbContext = new DomainContext(builder.Options); DbContext.Database.EnsureCreated(); } public ITestDatabase TestDatabase { get; } public DomainContext DbContext { get; } public void Dispose() { TestDatabase.Drop(); } }
-
Add the
DatabaseFixture
as part of theSetUp
andTearDown
methods in your test fixtures.[TestFixture] public class DomainContextTests { private DatabaseFixture _fixture; private DomainContext _domainContext; [SetUp] public void Setup() { _fixture = new DatabaseFixture(); _domainContext = _fixture.DbContext; } [TearDown] public void Teardown() { _fixture.Dispose(); } private async Task<User> AddEntity() { var entity = await _domainContext.Users.AddAsync(new User { Username = "Alice" }); await _domainContext.SaveChangesAsync(); return entity.Entity; } [Test] public async Task should_add_entity() { var user = await AddEntity(); var count = await _domainContext.Users.CountAsync(); Assert.NotNull(user.Id); Assert.AreEqual(1, count); } }
The examples below assume XUnit as the testing framework. These examples are taken directly
from TransientContext.Tests.Xunit
.
-
Begin by creating a database fixture. In the example below,
DomainContext
represents theEntityFramework
DBContext that is being created. For reference, seeTransientContext.Tests.NUnit/Common/Data/DomainContext.cs
.public class DatabaseFixture : IDisposable { public DatabaseFixture() { var configuration = new ConfigurationBuilder() .AddUserSecrets("your-secret-guid") .Build(); TestDatabase = new TestDatabaseBuilder() .WithConfiguration(configuration) .Build(); TestDatabase.Create(); var builder = new DbContextOptionsBuilder<DomainContext>(); builder.UseNpgsql(TestDatabase.ConnectionString); DbContext = new DomainContext(builder.Options); DbContext.Database.EnsureCreated(); } public ITestDatabase TestDatabase { get; } public DomainContext DbContext { get; } public void Dispose() { TestDatabase.Drop(); } } [CollectionDefinition("Database")] public class DatabaseCollectionFixture : ICollectionFixture<DatabaseFixture> { }
-
Add the
DatabaseFixture
as part of a test class constructor.[Collection("Database")] public class UserTests { private readonly TestDbContext _testDbContext; public UserTests(DatabaseFixture databaseFixture) { _testDbContext = databaseFixture.DbContext; } [Fact] public async Task InsertUsers() { await _testDbContext.Users.AddAsync(new User {Username = "Alice"}); await _testDbContext.Users.AddAsync(new User {Username = "Jane"}); await _testDbContext.SaveChangesAsync(); var count = await _testDbContext.Users.CountAsync(); Assert.Equal(2, count); } }