Как тестировать логику доступа к базе данных?

У меня есть проект на основе EF Code First с помощью MSSQL server, В одном из моих репозиториев я динамически строю запрос, используя PredicateBuilder, Проверка всех возможных результатов вручную каждый раз, когда что-то меняется в коде, очень трудоемка.

По этой причине я хотел бы автоматизировать это путем модульного тестирования. Я думал об использовании sql compact для модульного тестирования и MSSQL server для производства. Но как можно включить миграции для sql compact сервер?

Это класс dbContext:

public partial class ApplicationDbContext :
        IdentityDbContext<ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
    public ApplicationDbContext() : base("name=DefaultConnection") { }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());
        base.OnModelCreating(modelBuilder);
     }
}

Repository:

public class FilterRepository : IFilterRepository
{
    private ApplicationDbContext _dbContext;

    public FilterRepository(ApplicationDbContext dbContext)
    {
        _dbContext = dbContext;
        DbInterception.Add(new CommandInterceptor());
    }

    public IEnumerable<Person> GetPersons(Filter filter)
    {
        try
        {
            var persons = PredicateBuilder.False<Person>();

            _dbContext.Configuration.AutoDetectChangesEnabled = false;

            var result = _dbContext.Persons
                            .AsNoTracking() 
                            .Where(persons)
                            .OrderBy(x => x.Name)
                            .Skip(filter.Skip)
                            .Take(10)
                            .ToList();

            _dbContext.Configuration.AutoDetectChangesEnabled = true;

            return result;
        }
        catch (Exception ex)
        {

        }
    }
}

1 ответ

Решение

Хорошо, так что переключение на другую базу данных для тестирования (Imo) плохая идея.

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

Модульное тестирование предназначено для тестирования функциональности вашего бизнеса. Обычно вы просто копируете для этого свои данные, поскольку хотите проверить, что происходит с вашими входными данными (данными) внутри классов вашего домена, а не с того, откуда они пришли.

Интеграционный тест предназначен для проверки того, как уровень вашего бизнес-домена взаимодействует с вашим сервисным уровнем (ваш уровень данных является сервисным уровнем). Я бы также рассмотрел проверку правильности запроса как интеграционный тест для целей их выполнения.

Так что в вашем случае не путайте вещи и, возможно, добавьте неожиданное поведение, вызванное различиями в работе двух баз данных. Если вы тестируете свою бизнес-функциональность, смейтесь над этими данными. Для начала это быстрее, и вы будете тестировать именно то, что хотите тестировать.

Проведя интеграционное тестирование, вы проверяете, что ваше взаимодействие с сервисным уровнем корректно, в этом случае ваш тест на самом деле не проверяет, работает ли бизнес-логика, что должно быть рассмотрено в модульных тестах; Убедитесь, что ваши запросы возвращают правильные данные для своих предикатов и что все данные, которые должны быть сохранены, сохраняются правильно. Кроме того, любые транзакции в игре работают так, как вы ожидаете. Сквозное тестирование сценария также является действительным интеграционным тестом.

Вы обязательно должны делать это на той же платформе базы данных, что и ваша продукция, не ожидайте, что SQL Compact и SQL Server будут вести себя одинаково.

Редактировать... Для комментария.

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

Идея состоит в том, что в вашем доменном классе, который использует ваши данные, вы сначала получите свой репозиторий или класс запросов из контейнера DI, который был либо внедрен в конструктор, либо извлечен из контейнера DI.

// in your domain class you would have something like...
    var repo = container.Get<IRepository>();
    var myList = repo.GetMyObjects(predcate);

Так что с Moq вы могли бы просто посмеяться над этим вызовом

//Where you do your container registration..
var repo = Mock<IRepository>
repo.Setup( o => o.GetMyObject(predecate)).Returns( (predecate) => <your dummy list>));
container.Register(repo.Object);
// Then later on your business domain object gets the dummy repo instead.

Обратите внимание, что это псевдокод, будет немного отличаться в зависимости от используемых DI и Mocking сред.

Другие вопросы по тегам