c# - 如何参数化 xunit 类夹具?
问题描述
xUnit 提供了(共享)类固定装置的概念,如测试之间的共享上下文中所述。到目前为止,我还没有弄清楚是否有一种方法可以对此类固定装置进行参数化。例如,如果DatabaseFixture
应该用一些依赖于它所针对的测试的测试数据来丰富它怎么办?测试类可能想要插入测试数据,但只插入一次,然后针对该数据库(夹具)运行所有测试。
换句话说,如果// ... initialize data in the test database ...
来自文档(上面引用)也取决于测试怎么办?因为并非所有测试都可能希望拥有相同的测试数据。实际上,我什至认为很多时候测试定义自己的测试数据而不是在测试数据级别上耦合测试是一种很好的做法。
到目前为止,我正在做的解决方法是提供一种ConfiguredWith
方法,该方法接受只执行一次的回调。为了做到这一点,我需要延迟测试数据库的初始化,以便确定配置选项已设置。就像是:
public class MyDatabaseTests : IClassFixture<DatabaseFixture>
{
DatabaseFixture fixture;
public MyDatabaseTests(DatabaseFixture fixture)
{
this.fixture = fixture;
this.fixture.ConfigureWith(new DatabaseFixtureOptions
{
InitTestData = db => db.Insert(...);
};
}
// ...
}
这看起来相当做作,因为在针对数据库编写测试时感觉像是标准要求。
如果 xUnit 不提供这种开箱即用的功能,也许有人有更好的模式来解决这个问题。
这个问题似乎朝着类似的方向发展,但我不一定固定在具有这种结构的解决方案上。
解决方案
我了解到,由于 xUnit 的并行执行,实体框架会抛出异常,因为它已经跟踪到了尝试共享实体框架数据库上下文IClassFixture
或CollectionFixtures
最终导致测试被另一个测试数据或死锁/竞争条件污染的艰难方法。具有给定 ID 的对象和更多类似的头痛。就个人而言,我建议针对您的特定使用原因,将数据库上下文创建/清理保留在constructor/dispose
替代方案中,例如:
public class TestClass : IDisposable
{
DatabaseContext DatabaseContext;
public TestClass()
{
var options = new DbContextOptionsBuilder<DatabaseContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;
DatabaseContext = new DatabaseContext(options);
//insert the data that you want to be seeded for each test method:
DatabaseContext.Set<Product>().Add(new Product() { Id = 1, Name = Guid.NewGuid().ToString() });
DatabaseContext.SaveChanges();
}
[Fact]
public void FirstTest()
{
var product = DatabaseContext.Set<Product>().FirstOrDefault(x => x.Id == 1).Name;
//product evaluates to => 0f25a10b-1dfd-4b4b-a69d-4ec587fb465b
}
[Fact]
public void SecondTest()
{
var product = DatabaseContext.Set<Product>().FirstOrDefault(x => x.Id == 1).Name;
//product evaluates to => eb43d382-40a5-45d2-8da9-236d49b68c7a
//It's different from firstTest because is another object
}
public void Dispose()
{
DatabaseContext.Dispose();
}
}
当然你总是可以做一些改进,但想法就在那里
推荐阅读
- excel - 执行此代码后 VBA 宏冻结
- c#-4.0 - 在 C# 中连接后内存中的字符串对象
- python - 您可以使用 Jenkins 远程触发以在您的存储库中运行脚本吗(该脚本与构建无关)
- python - ND 索引与 NumPy 中的默认值
- sql-server - 如何将数据类型 VARCHAR 更改为 DATETIME?
- python - 一种更 Pythonic 的排列方式?
- batch-file - 安装字体的批处理脚本未设置 fext 变量
- swift - 我如何获得表格视图(swift)中分数的平均值?
- assembly - GAS 汇编器 - Fgets 函数 SegFaults
- excel - 清除关键字前的单元格内容