Entity framework core 如何包装在数据库事务中使用TestServer的集成测试?

Entity framework core 如何包装在数据库事务中使用TestServer的集成测试?,entity-framework-core,xunit,Entity Framework Core,Xunit,使用xUnit和Microsoft.AspNet.TestHost中的TestServer,如何将每个测试包装在一个数据库事务中,以便在测试后回滚 下面是我如何创建TestServer: TestServer = new TestServer(TestServer.CreateBuilder() .UseStartup<Startup>()); 我可以将DbContext从服务中拉回来,并在Startup类中存储一个静态引用,但这似乎很有技巧。是否有任何方法可以实例化DbC

使用xUnit和Microsoft.AspNet.TestHost中的
TestServer
,如何将每个测试包装在一个数据库事务中,以便在测试后回滚

下面是我如何创建
TestServer

TestServer = new TestServer(TestServer.CreateBuilder()
    .UseStartup<Startup>());
我可以将
DbContext
从服务中拉回来,并在
Startup
类中存储一个静态引用,但这似乎很有技巧。是否有任何方法可以实例化
DbContext
,在这里我创建
TestServer
,并让web应用程序使用它,而不是
Startup
类中的一个


编辑:我尝试实例化另一个
DbContext
实例,在其中创建
TestServer
,并在每次测试之前使用该上下文删除和重新创建数据库,但这会给每个测试的运行时间增加大约10秒。

一些建议:最简单的方法是在测试结束时销毁测试数据库,并为每个测试运行重新创建数据库。这确保了测试污染时不会出现延迟测试

但既然您问了如何扩展Xunit,这可以通过扩展Xunit来实现。Xunit允许您定义自定义测试用例和测试运行程序。完整的答案很难包含在SO答案中。最简单的解决方案使用环境事务。(危险!环境事务可能很棘手。)Xunit有一个用于回滚事务的自定义BeforeAfterTestAttribute的示例。要使用环境事务,请关闭在存在环境事务时引发的默认EF设置。(
optionsBuilder.UseSqlServer().SuppressAmbientTransactionWarning()

一个更复杂但更好的解决方案是重写
XunitTestCaseRunner
,并向每个测试用例中注入一个事务,确保在每个测试结束时回滚

此外,EF文档还提供了使用InMemory提供程序进行测试的示例。你可能会发现这很有用。

services.AddEntityFramework()
    .AddSqlServer()
    .AddDbContext<TrailsDbContext>(options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));