c# - XUnit 测试的 EF Core DbContext 并发问题

标签 c# entity-framework-core xunit

我似乎遇到了一个奇怪的并发问题,我似乎无法指出。 当我构建 DbContext 的实现时,我注入(inject)了我想要由模型构建器构建的实体(不用担心为什么)。这仅由我的应用程序在运行时完成一次并且运行良好,但是当我对数据库集成进行集成测试时,我仅注入(inject) InMemoryDatabase 所需的测试实体。

现在我似乎遇到了一个奇怪的问题,不同类文件中需要不同实体的两个单元测试似乎被交叉了。

我继续运行单元测试,第一个测试将通过,但第二个测试将失败,并提示 TestObjectB 在模型中不存在。当我检查模型时,它说 TestObjectA 存在,即使它没有在此测试中注入(inject)。因此,就好像 DataContext 的实现是静态的并被覆盖一样......这些是不同的文件和上下文的新构造函数,我不明白它们是如何交叉路径的?如果我运行的单元测试本身失败了,它就会通过。

请注意,以下代码已针对您的 View 进行了简化。

数据库上下文:

public class DataContext : DbContext
{
    private readonly List<IEntity> _entities;

    public DataContextA(List<IEntity> entities, DbContextOptions options) : base(options)
    {
        _entities = entities;
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        foreach (var entity in _entities)
        {
            modelBuilder.Entity(entity.GetType());
        }
    }
}

测试实现1:

[Fact]
            public void CheckUniqueFieldA()
            {
                var options = new DbContextOptionsBuilder<DataContext>();

                options.UseInMemoryDatabase(Guid.NewGuid().ToString());

                using (var context = new DataContext(new List<IEntity> { new TestObjectA() }, options.Options))
                {
                    //Do Something
                }
            }

测试实现2:

[Fact]
            public void CheckUniqueFieldB()
            {
                var options = new DbContextOptionsBuilder<DataContext>();

                options.UseInMemoryDatabase(Guid.NewGuid().ToString());

                using (var context = new DataContext(new List<IEntity> { new TestObjectB() }, options.Options))
                {
                    //Do Something
                }
            }

最佳答案

原因是 Alternating between multiple models with the same DbContext type 中描述的 EF Core 模型缓存。文档主题:

...the model caching mechanism EF uses to improve the performance by only invoking OnModelCreating once and caching the model.

By default EF assumes that for any given context type the model will be the same.

该链接还包含一个如何解决该问题的示例。您需要创建 IModelCacheKeyFactory 接口(interface)的自定义实现,并使用 OnConfiguring 内的 ReplaceService 替换默认的 EF Core 实现。该实现应该返回一个对象,表示给定 DbContext 实例的唯一缓存键。默认实现仅返回context.GetType()

关于c# - XUnit 测试的 EF Core DbContext 并发问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56311901/

相关文章:

c# - 是否可以在 EntityCollection<T> 上实现 RemoveAll()?

c# - 无法在 WCF REST 服务中反序列化 XML

c# - Azure Functions 使用两个输出 blob 调整 blob 大小

asp.net-core - 使用 EF7 命令时 IHostingEnvironment.WebRootPath 为 null

c# - 多上下文内存数据库

c# - Response.Redirect ("Sign up.aspx",false);

entity-framework - 如何处理减慢构建和 IDE 的巨大 efcore 迁移设计器文件

nunit - sonarqube 中的 Xunit 支持

c# - 断言 xunit 中存在文件的惯用方法是什么?

c# - 如何在不进行单元测试的情况下运行 .NET 方法?