我似乎遇到了一个奇怪的并发问题,我似乎无法指出。 当我构建 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/