使用 xUnit 和 Microsoft.AspNet.TestHost 中的TestServer
,如何将每个测试包装在测试后可以回滚的数据库事务中?
以下是我创建TestServer
的方式:
TestServer = new TestServer(TestServer.CreateBuilder()
.UseStartup<Startup>());
此处引用的Startup
是 Web 应用项目中的Startup
。在该Startup
类的ConfigureServices
方法中,我像这样添加 EF:
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<TrailsDbContext>(options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
我可以拉回服务的DbContext
并在Startup
类上存储静态引用,但这似乎很笨拙。有什么方法可以实例化我创建TestServer
的DbContext
,并以某种方式让 Web 应用程序使用它而不是 Startup
类中的应用程序?
编辑:我尝试实例化DbContext
的另一个实例,在其中创建TestServer
,并在每次测试之前使用该上下文删除并重新创建数据库,但这会增加大约 10 秒每个测试的运行时间。
一些建议:最简单的方法是在最后销毁测试数据库,然后为每个测试运行重新创建。这确保了没有挥之不去的测试间污染。
但是既然你问了怎么做,这可以通过扩展Xunit来完成。Xunit 允许您定义自定义测试用例和测试运行程序。完整的答案很难包含在 SO 答案中。最简单的解决方案使用环境事务。(危险!环境事务可能很棘手。Xunit 有一个回滚事务的自定义 BeforeAfterTestAttribute 示例。https://github.com/xunit/samples.xunit/tree/master/AutoRollbackExample。若要使用环境事务,请关闭在存在环境事务时引发的默认 EF 设置。(optionsBuilder.UseSqlServer().SuppressAmbientTransactionWarning()
(。
一个更复杂但更好的解决方案是覆盖XunitTestCaseRunner
并将事务注入每个测试用例,确保在每个测试结束时回滚。
此外,EF 文档还提供了使用 InMemory 提供程序进行测试的示例。您可能会发现这很有用。"在内存中测试:EF Core 文档">