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