I’m curious if anyone has gone down the road of transactional integration testing with aspnet and ef core? I want to be able to perform full integration tests all the way to the db (not using an in-memory db). There are 2 problems:
I would like to wrap tests in a transaction (_dbContext.Database.BeginTransactionAsync()
). The problem is the DbContext I get from:
_server = new TestServer(builder);
_services = _server.Host.Services;
_dbContext = (AppDbContext)_services.GetService(typeof(AppDbContext))
Will be in a different scope (so a different instance) than the one that gets resolved by the AspNetCore middleware. So, only the test code would be transactional, not any code executed by the TestServer
. I have considered using some test middleware in a TestStartup
class that would wrap the API code in a transaction, but the problem there is it will be disposed/rolled back before the test can evaluate it. Consider the following use case:
In this case, the test needs access to the same dbContext instance used by the test server.
I tried a few hacky ways of passing the context using AsyncLocal
which didn’t work so then I just tried using a simple static
member. But, that also didn’t work, so it appears there is some AppDomain isolation between the test app and the
I’m curious if anyone has gone down this road and if so, what they came up with?TestServer
.
Just closing out this issue. The solution was to register the DbContext as a singleton in the test startup class. So, in tests:
services.AddDbContext<HostContext>(Configure, ServiceLifetime.Singleton);
But, in the application it would be registered as:
services.AddDbContext<HostContext>(Configure, ServiceLifetime.Transient);
UPDATE
A more complete answer has been posted here http://nance.io/leveling-up-your-dotnet-testing-transactional-integration-testing-in-asp-net-core/