Конфликт поддерживаемых модульных тестов - PullRequest
0 голосов
/ 02 ноября 2018

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

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

Неважно, если я запускаю тесты параллельно или нет.

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

Не удалось сохранить или принять изменения, поскольку несколько объектов типа «Center.Shared.Person» имеют одно и то же значение первичного ключа. Убедитесь, что явно установленные значения первичного ключа являются уникальными. Убедитесь, что сгенерированные базой данных первичные ключи правильно настроены в базе данных и в модели Entity Framework. Используйте Entity Designer для конфигурации базы данных сначала / модели первой. Используйте свободный 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 перестает работать при использовании базы данных в памяти?

1 Ответ

0 голосов
/ 02 ноября 2018

Я пытался использовать неявный подход, где все подключается через настройки в файле 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) { }

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

...