Shim DbContext ctor для тестирования модулей усилия

effort entity-framework microsoft-fakes shim unit-testing

Вопрос

Я хотел бы перехватить var context = new MyDbContext() чтобы вместо этого вызвать другой вызов конструктора.

Самое замечательное в EFfort заключается в том, что он позволит вам создать легкую базу данных в памяти для модульного тестирования.

var connection = Effort.DbConnectionFactory.CreateTransient();
var testContext = new MyDbContext(connection);

Но тогда вам придется вводить этот context в ваш репозиторий.

var connection = Effort.DbConnectionFactory.CreateTransient();
var testContext = new MyDbContext(connection);

Можно ли просто перехватить var context = new MyDbContext() , чтобы он возвращал testContext ?

var connection = Effort.DbConnectionFactory.CreateTransient();
var testContext = new MyDbContext(connection);

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

(edit: Я просто понял, что это фактически не возвращает другой вызов ctor, работая над ним.)

Догадаться. Достаточно просто, если вы знаете, как это сделать:

        [TestMethod]
        public void Should_have_a_name_like_this()
        {
            // Arrange
            var connection = Effort.DbConnectionFactory.CreateTransient();
            ShimSolrDbContext.Constructor = context => new SolrDbContext(connection);

            // Act


            // Assert

        }

И, как обычно, EFfort требует этого конструктора в классе DbContext:

        [TestMethod]
        public void Should_have_a_name_like_this()
        {
            // Arrange
            var connection = Effort.DbConnectionFactory.CreateTransient();
            ShimSolrDbContext.Constructor = context => new SolrDbContext(connection);

            // Act


            // Assert

        }

Но это означает, что репо блаженно не осознает особую переходную связь:

        [TestMethod]
        public void Should_have_a_name_like_this()
        {
            // Arrange
            var connection = Effort.DbConnectionFactory.CreateTransient();
            ShimSolrDbContext.Constructor = context => new SolrDbContext(connection);

            // Act


            // Assert

        }

Популярные ответы

У вас есть два возможных варианта. Использование заводов или через Aspect-ориентированное программирование (например, PostSharp)

ссылка на эту статью: http://www.progware.org/Blog/post/Interception-and-Interceptors-in-C-(Aspect-oriented-programming).aspx

Использование PostSharp (AOP)

PostSharp - отличный инструмент и может обеспечить самый чистый перехват (что не означает никаких изменений в ваших классах и генерации объектов вообще, даже если вы не делаете свои фабрики для создания объектов и / или интерфейсов), но это не бесплатная библиотека. Вместо того, чтобы создавать прокси во время выполнения, он вводит код во время компиляции и поэтому автоматически меняет исходную программу, чтобы добавить метод перехвата.
.....
Самое приятное в этом заключается в том, что вы не изменяете ничего другого в своем коде, поэтому ваш объект может быть сгенерирован с использованием нового ключевого слова.

Использование DI и Factory-pattern

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

public interface IDbContextFactory<T> where T : DbContext {
    T Create();
}

public class TestDbContextFactory : IDbContextFactory<MyDbContext> {
    public MyDbContext Create() {
        var connection = Effort.DbConnectionFactory.CreateTransient();
        var testContext = new MyDbContext(connection);
        return testContext;
    }
}

public class FooRepository {
    MyDbContext _context;
    public FooRepository(IDbContextFactory<MyDbContext> factory) { 
        _context = factory.Create(); 
    }
}



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