EF Core DbContext Проблема параллелизма с тестами XUnit - PullRequest
1 голос
/ 26 мая 2019

У меня, кажется, странная проблема с параллелизмом, на которую я, похоже, не могу понять.Когда я создаю свою реализацию DbContext, я внедряю сущности, которые я хочу создать с помощью разработчика моделей (не беспокойтесь о том, почему).Это делается только один раз моим приложением во время выполнения и работает нормально, но когда я провожу интеграционное тестирование интеграции БД, я внедряю только те тестовые объекты, которые мне нужны для моей InMemoryDatabase.

Теперь у меня возникает странная проблемагде два модульных теста в разных файлах классов, нуждающихся в разных сущностях, похоже, пересекаются.

Я продолжаю выполнять модульные тесты, и первый тест пройдёт, но второй тест не пройдёт, сказав, что TestObjectB не существует в модели.Когда я проверяю модель, она говорит, что вместо этого существует TestObjectA, хотя он и не вводился в этом тесте.Как если бы реализация DataContext была статической и перезаписанной ... Это разные файлы и свежие конструкторы для контекста, я не понимаю, как они пересекаются?Если я запускаю модульное тестирование, которое само по себе не проходит, оно проходит.

Обратите внимание, что следующий код был упрощен для вашего просмотра.

Контекст БД:

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
                }
            }

1 Ответ

2 голосов
/ 26 мая 2019

Причина в том, что кэширование модели EF Core описано в Чередование между несколькими моделями с одним и тем же типом DbContext Тема документации:

... механизм кэширования модели, который EF использует для улучшенияпроизводительность, только вызывая OnModelCreating один раз и кэшируя модель.

По умолчанию EF предполагает, что для любого данного типа контекста модель будет одинаковой.

Ссылка также содержит пример, как ее решить.Вам необходимо создать пользовательскую реализацию интерфейса IModelCacheKeyFactory и заменить реализацию EF Core по умолчанию, используя ReplaceService внутри OnConfiguring.Реализация должна возвращать объект, представляющий уникальный ключ кэша для данного экземпляра DbContext.Реализация по умолчанию просто возвращает context.GetType().

...