将数据添加到 DbContext 仅限一次。

3

我创建了一个XUnit Fixture来定义EF Core上下文的初始数据:

public class ServiceProviderFixture : IDisposable {

  public IServiceProvider Provider { get; private set; }

  public ServiceProviderFixture() {
    IServiceCollection services = new ServiceCollection();
    services.AddDbContext<Context>(x => { x.UseInMemoryDatabase("Database"); });
    Provider = services.BuildServiceProvider();
    BuildContext();
  }

  private void BuildContext() { 
    Context context = Provider.GetService<Context>();
    context.Countries.Add(new Country { Code = "fr", Name = "France" });
    context.SaveChanges();
  }

  public void Dispose() { } 

} 

然后在一些测试中,我使用它如下:

 public class TestMethod1 : IClassFixture<ServiceProviderFixture> {

   public Test(ServiceProviderFixture fixture) {
    _fixture = fixture;
   } 

  [Fact]
  public async Task Test1() {

    IServiceProvider provider = _fixture.Provider;

    Context context = provider.GetService<Context>();

    // Add test data to context
    // Test some method

  }

} 

当我运行一个测试时,一切都很顺利... 但是当我使用dotnet test来运行所有的测试时,我得到了以下内容:

An item with the same key has already been added. Key: fr
The following constructor parameters did not have matching fixture data:
ServiceProviderFixture fixture)

我认为BuildContext()在同一上下文中每个TestClass只会被调用一次。
我该如何解决这个问题?
2个回答

2

由于您总是以相同的方式命名内存数据库,因此您总是会再次获得相同的数据库。

您必须为每个测试用例命名不同的数据库(例如Guid.NewGuid().ToString())。

services.AddDbContext<Context>(x => 
    x.UseInMemoryDatabase($"Database{Guid.NewGuid()}")
);

1

只需在您的BuildContext中检查是否有任何数据,如果没有则创建数据,否则不执行任何操作。或者在测试完成后可以清除已创建的数据。

  private void BuildContext() { 
    Context context = Provider.GetService<Context>();
    if(!context.Countries.Any())
    {
        context.Countries.Add(new Country { Code = "fr", Name = "France" });
        context.SaveChanges();
    }
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接