如何参数化xunit类夹具?

时间:2020-11-12 08:15:45

标签: c# xunit xunit.net

xUnit提供了Shared Context between Tests中所述的(共享)类固定装置的概念。到目前为止,我还没有弄清楚是否有一种参数化此类固定装置的方法。例如,如果 calendar.setTimeInMillis(Long.parseLong(orderTime)); 应该充实一些测试数据,这取决于所运行的测试?一个测试类可能想只插入一次测试数据,但只一次,然后针对该数据库(夹具)运行所有测试。

换句话说,如果文档中的DatabaseFixture(上面引用)也取决于测试,该怎么办?因为并非所有测试都希望具有相同的测试数据。实际上,我什至认为,很多时候将测试定义自己的测试数据而不在测试数据的级别上进行耦合是一种好习惯。

到目前为止,我正在解决的问题是提供一种// ... initialize data in the test database ...方法,该方法接受仅执行一次的回调。为了做到这一点,我需要懒惰地推迟测试数据库的初始化,以便确保设置了配置选项。像这样:

ConfiguredWith

对于针对数据库编写测试时感觉像是标准要求的事情,这似乎是人为的。

如果xUnit不提供现成的功能,也许有人对如何解决这个问题有了更好的模式。

This question似乎朝着相似的方向发展,但我不一定要固定在具有这种结构的解决方案上。

1 个答案:

答案 0 :(得分:0)

我了解了一种艰难的方法,即试图通过IClassFixtureCollectionFixtures共享实体框架数据库上下文,最终将导致最终的测试被另一个测试数据污染或由于并行而导致死锁/竞争条件执行xUnit时,实体框架会引发异常,因为它已经使用给定的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();
        }
    }

当然,您总是可以进行一些改进,但是想法就在那里