Конфликт поддерживаемых модульных тестов

c# effort entity-framework-6 unit-testing vstest

Вопрос

Я унаследовал несколько тестов с этим проектом. Они работали при работе с базой данных SQL, но медленно. Я пытаюсь перейти на использование усилий.
.NET4.5, EF6.2, усилие 1.3.10.

У меня есть две проблемы, связанные с моими юнит-тестами.

Не имеет значения, буду ли я запускать тесты параллельно или нет.

1) Если я запускаю более одного за раз, я получаю

Не удалось сохранить или принять изменения, так как несколько объектов типа «Center.Shared.Person» имеют одно и то же значение первичного ключа. Убедитесь, что явно установленные значения первичного ключа являются уникальными. Убедитесь, что сгенерированные базой данных первичные ключи правильно настроены в базе данных и в модели Entity Framework. Используйте Entity Designer для базы данных First / Model First. Используйте свободный API «HasDatabaseGeneratedOption» или «DatabaseGeneratedAttribute» для конфигурации Code First. ---> System.InvalidOperationException: сбой при сохранении или принятии изменений, так как несколько сущностей типа «Center.Shared.Person» имеют одинаковое значение первичного ключа. Убедитесь, что явно заданные значения первичного ключа уникальны. Убедитесь, что сгенерированные базой данных первичные ключи правильно настроены в базе данных и в модели Entity Framework. Используйте конструктор Entity Designer для базы данных First / Model First. Используйте свободный API-интерфейс HasDatabaseGeneratedOption или 'DatabaseGeneratedAttribute' для конфигурации Code First ..

Таким образом, похоже, что тесты не являются должным образом изолированными.
Прослеживая код, я вижу, что вызывается CreateTransient, но он, по-видимому, не является достаточно быстрым.

    public DbConnection CreateConnection(string nameOrConnectionString)
    {
        lock (_lock)
        {
            if (_connection == null)
            {
                _connection = Effort.DbConnectionFactory.CreateTransient();
            }

            return _connection;
        }
    }

В процедуре TestInitialize я пытаюсь сбросить базу данных.

    [TestInitialize]
    public override void Initialize()
    {
        db.Database.Delete();
        db.Database.CreateIfNotExists();
        db.Database.Initialize(true);

Это очень сложный код, поэтому, если нам нужно разместить больше кода, пройдет много времени, прежде чем мы доберемся до дна кроличьей норы. Вероятно, лучше создать PoC.

2) Если я запускаю тесты самостоятельно, у меня возникает другая проблема. Опять же, они прошли против SQL, но не Effort.

    [TestMethod]
    public void ClientAccessorTests_Find()
    {
        Client result;
        Client client = new Client()
        {
            Complete = false,
            HeadOfHousehold = true,
            PersonID = _person.PersonID
        };

        _accessor.Create(client, _accessor.DefaultConnectionContext);

        result = _accessor.Find(new object[] { client.ClientID }, _accessor.DefaultConnectionContext);

        Assert.IsNotNull(result);  // Fails with Assert.IsNotNull failed. 
    }

Создать состоит из

    public virtual EntityType Create(EntityType entity, ConnectionContext connectionContext)
    {
        IsContextValid(connectionContext);
        if (entity == null) throw new ArgumentException("", "entity");

        using (var db = CreateDbContext<DbContextType>(connectionContext))
        {
            db.Set<EntityType>().Add(entity);
            db.SaveChanges();
        }

        return entity;
    }

Найти состоит из

    public virtual EntityType Find(object[] primaryKey, ConnectionContext connectionContext)
    {
        IsContextValid(connectionContext);
        if (primaryKey == null || primaryKey.Length == 0) throw new ArgumentException("", "primaryKey");

        using (var db = CreateDbContext<DbContextType>(connectionContext))
        {
            return db.Set<EntityType>().Find(primaryKey);
        }
    }

Я знаю, что он вызывает CreateDbContext, но отслеживает код, насколько я могу судить, похоже, что это та же база данных с тем же идентификатором.

Что должно стать причиной изоляции тестов?
И есть идеи, почему Find перестает работать при использовании базы данных в памяти?

Принятый ответ

Я пытался использовать неявный подход, где все подключается через настройки в файле app.config.
Мне повезло больше, когда я отказался от этого подхода, создал соединение с базой данных и установил его явно.

        System.Data.Common.DbConnection connection = new EffortProviderFactory("").CreateConnection("");
        _accessor = new ClientAccessor();
        _accessor.Connection = connection;
        db = new EntitiesDb(connection);

Базовый Accessor создает копии БД на каждом шагу, что хорошо, если он использует одно и то же DbConnection. Поэтому я установил это на метод доступа, а затем использовал его здесь:

        if (_connection == null) {   // this is the path for the application
            if (connectionContext == null) {
                ret = new T();
            } else {
                ret = (T)Activator.CreateInstance(typeof(T), new object[] { connectionContext });
            }
        } else {  // this is the path for unit tests.
            ret = (T)Activator.CreateInstance(typeof(T), new object[] { _connection });
        }

Наконец, мне пришлось добавить конструктор, который использовал DbConnection для DbContext и его потомков.

    public EntitiesDb(DbConnection connection) : base(connection) { }

«Найти» теперь работает, и тесты не мешают друг другу.
Следующий шаг - это подтолкнуть все это к базовым классам.



Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему