EntityFramework, DbContextScope и Effort - исключение: DbContext размещен внутри модульного теста

c# dbcontext effort entity-framework unit-testing

Вопрос

Я пытаюсь написать модульные тесты (с NUnit) для уровня сервиса, который использует:

  1. Entity Framework в качестве уровня доступа к данным
  2. DbContextScope для управления временем жизни DbContext

Я также использую Effort.EF6 для издевательства DbContext в модульных тестах. К сожалению, я не могу найти способ сделать DbContextScope совместимым с Effort, чтобы я мог правильно протестировать все случаи.


Обзор кода

Сервисный уровень состоит из классов (служб), которые выполняют некоторую бизнес-логику. Каждый метод рассматривается как полная транзакция, заканчивающаяся context.SaveChanges() . Пример:

    private IDbContextScopeFactory _dbContextScopeFactory;

    public DepartmentsService(IDbContextScopeFactory dbContextScopeFactory)
    {
        _dbContextScopeFactory = dbContextScopeFactory;
    }

    public BusinessModel.Department Insert(BusinessModel.Department department)
    {
        using (var dbContextScope = _dbContextScopeFactory.Create())
        {
            // Validation
            ValidateAndThrowOnFailure(department, new DepartmentAddValidator());

            // Operation
            DBModel.Department newDepartment = Mapper.Map<DBModel.Department>(department);

            newDepartment.InsertDateUTC = DateTime.UtcNow;

            dbContextScope.DbContexts.Get<DPSContext>().Departments.Add(newDepartment);
            dbContextScope.SaveChanges();

            return Mapper.Map<BusinessModel.Department>(newDepartment);
        }
    }

Для модуляции теста такого метода, я делаю некоторую подготовку перед каждым тестом:

    private IDbContextScopeFactory _dbContextScopeFactory;

    public DepartmentsService(IDbContextScopeFactory dbContextScopeFactory)
    {
        _dbContextScopeFactory = dbContextScopeFactory;
    }

    public BusinessModel.Department Insert(BusinessModel.Department department)
    {
        using (var dbContextScope = _dbContextScopeFactory.Create())
        {
            // Validation
            ValidateAndThrowOnFailure(department, new DepartmentAddValidator());

            // Operation
            DBModel.Department newDepartment = Mapper.Map<DBModel.Department>(department);

            newDepartment.InsertDateUTC = DateTime.UtcNow;

            dbContextScope.DbContexts.Get<DPSContext>().Departments.Add(newDepartment);
            dbContextScope.SaveChanges();

            return Mapper.Map<BusinessModel.Department>(newDepartment);
        }
    }

Тест и проблема

Вот простой единичный тест:

    private IDbContextScopeFactory _dbContextScopeFactory;

    public DepartmentsService(IDbContextScopeFactory dbContextScopeFactory)
    {
        _dbContextScopeFactory = dbContextScopeFactory;
    }

    public BusinessModel.Department Insert(BusinessModel.Department department)
    {
        using (var dbContextScope = _dbContextScopeFactory.Create())
        {
            // Validation
            ValidateAndThrowOnFailure(department, new DepartmentAddValidator());

            // Operation
            DBModel.Department newDepartment = Mapper.Map<DBModel.Department>(department);

            newDepartment.InsertDateUTC = DateTime.UtcNow;

            dbContextScope.DbContexts.Get<DPSContext>().Departments.Add(newDepartment);
            dbContextScope.SaveChanges();

            return Mapper.Map<BusinessModel.Department>(newDepartment);
        }
    }

Проблема в том, что сбой не выполняется:

    private IDbContextScopeFactory _dbContextScopeFactory;

    public DepartmentsService(IDbContextScopeFactory dbContextScopeFactory)
    {
        _dbContextScopeFactory = dbContextScopeFactory;
    }

    public BusinessModel.Department Insert(BusinessModel.Department department)
    {
        using (var dbContextScope = _dbContextScopeFactory.Create())
        {
            // Validation
            ValidateAndThrowOnFailure(department, new DepartmentAddValidator());

            // Operation
            DBModel.Department newDepartment = Mapper.Map<DBModel.Department>(department);

            newDepartment.InsertDateUTC = DateTime.UtcNow;

            dbContextScope.DbContexts.Get<DPSContext>().Departments.Add(newDepartment);
            dbContextScope.SaveChanges();

            return Mapper.Map<BusinessModel.Department>(newDepartment);
        }
    }

Кажется, что DbContextScope, используемый внутри метода Insert внутренне распределяет назначенные контексты в конце using блока, и, таким образом, Assert выдает исключение при вызове. Кто-нибудь сталкивается с подобной проблемой или просто знает, что я должен сделать, чтобы успешно проверить этот и подобные сценарии?

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

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

    public class TestableDPSContext : DBModel.DPSContext
    {
        public TestableDPSContext(DbConnection connection)
            : base(connection)
        {

        }

        protected override void Dispose(bool disposing)
        {
            // Do nothing
        }

        public void RealDispose(bool disposing)
        {
            // Invoke real dispose
            base.Dispose(disposing);
        }
    }

    [TearDown]
    public void FinishTest()
    {
        _dbEntities.RealDispose(false);
    }

Может быть, есть лучшее решение, но на данный момент кажется, что проблема с DbContext находится слишком рано в тестах.




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