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

时间:2016-02-16 20:49:00

标签: entity-framework-core xunit

使用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秒运行时间。

1 个答案:

答案 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"