C# 事务集成测试ASP.Net核心和实体框架核心
我很好奇是否有人使用aspnet和ef-core进行了事务集成测试?我希望能够执行到数据库的所有完整集成测试(不使用内存中的数据库)。有两个问题:C# 事务集成测试ASP.Net核心和实体框架核心,c#,asp.net,asp.net-core,.net-core,entity-framework-core,C#,Asp.net,Asp.net Core,.net Core,Entity Framework Core,我很好奇是否有人使用aspnet和ef-core进行了事务集成测试?我希望能够执行到数据库的所有完整集成测试(不使用内存中的数据库)。有两个问题: 测试可能有副作用,但应单独运行,因为副作用可能导致其他测试失败。我不想要求开发者在每次测试后编写过多的清理代码 我可以在每次测试运行时拆卸并重新创建db,但当测试计数开始达到100秒时,运行测试的速度变得令人无法忍受 我想在事务中包装测试(\u dbContext.Database.BeginTransactionAsync())。问题在于我从中
- 测试可能有副作用,但应单独运行,因为副作用可能导致其他测试失败。我不想要求开发者在每次测试后编写过多的清理代码李>
- 我可以在每次测试运行时拆卸并重新创建db,但当测试计数开始达到100秒时,运行测试的速度变得令人无法忍受
\u dbContext.Database.BeginTransactionAsync()
)。问题在于我从中获得的DbContext:
_server = new TestServer(builder);
_services = _server.Host.Services;
_dbContext = (AppDbContext)_services.GetService(typeof(AppDbContext))
将位于与AspNetCore中间件解析的不同的范围(因此是不同的实例)。因此,只有测试代码是事务性的,而不是由TestServer
执行的任何代码。我曾考虑在TestStartup
类中使用一些测试中间件,将API代码包装到事务中,但问题是,在测试评估它之前,它将被处理/回滚。考虑以下用例:
- 发送帖子以创建资源
- 断言dbContext包含资源
asynchlocal
传递上下文的黑客方法,但没有成功,所以我只是尝试使用一个简单的static
成员。但是,这也不起作用,因此在测试应用程序和TestServer
之间似乎存在一些AppDomain隔离。
我很好奇是否有人走上了这条路,如果有,他们想出了什么办法?刚刚结束这个问题。解决方案是在测试启动类中将DbContext注册为单例。因此,在测试中:
services.AddDbContext<HostContext>(Configure, ServiceLifetime.Singleton);
services.AddDbContext(Configure,servicelifest.Singleton);
但是,在申请中,它将注册为:
services.AddDbContext<HostContext>(Configure, ServiceLifetime.Transient);
services.AddDbContext(配置,servicelifest.Transient);
更新
这里发布了一个更完整的答案为什么不直接使用Microsoft.EntityFrameworkCore.InMemory进行测试呢?如上所述,我需要一直到数据库。我们的应用程序使用多个数据库提供程序(MS SQL Server和PostgreSQL),我们还希望验证特定于提供程序的迁移。因此,您希望以可能导致其他测试失败的方式更改数据库,并且不希望编写清理/恢复代码?是的。同时运行的测试可能会相互影响。或者它们可能有副作用,阻止其他测试假设它们在干净的环境中运行。我希望测试在一个不会产生副作用的事务中运行。这不是一个新概念,在rails中已经有一段时间了(参考事务性装置/测试)。测试不应关心它们是否影响其他测试。ASP.Net Core的DI Singleton不是传统Singleton模式的实现(即每个应用程序域一个实例)。相反,它是每个
IServiceProvider
实例的一个实例(在本例中,使用TestServer
创建)。这是因为每个测试都会收到一个唯一的TestServer
实例。Imagne指出,在运行应用程序时,实体上的导航属性为null,访问它时会引发null指针异常。在测试中可能无法检测到这一点,因为在Singleton DbContext中,该实体可能会从以前被记住,并且导航属性设置正确。所以测试可能会给出错误的图片。