1

我想拦截var context = new MyDbContext()以返回不同的构造函数调用。

EFfort的伟大之处在于它可以让您为单元测试设置一个简单的内存数据库。

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

但是你必须将它注入context到你的存储库中。

public FooRepository(MyDbContext context) { _context = context; }

是否有可能只是拦截var context = new MyDbContext(),以便它返回testContext

using (var context = new MyDbContext()) {
    // this way, my code isn't polluted with a ctor just for testing
}
4

2 回答 2

0

你有两个可能的选择。使用工厂或通过面向方面的编程(如 PostSharp)

参考这篇文章:http ://www.progware.org/Blog/post/Interception-and-Interceptors-in-C-(Aspect-oriented-programming).aspx

使用 PostSharp (AOP)

PostSharp 是一个很棒的工具,可以实现最干净的拦截(这意味着即使您没有创建对象和/或接口的工厂,您的类和对象生成也不会发生任何变化),但它不是一个免费的库。它不是在运行时创建代理,而是在编译时注入代码,因此以无缝方式更改您的初始程序以添加方法拦截。
.....
很酷的一点是您无需更改代码中的任何其他内容,因此您的对象仍然可以使用 new 关键字生成。

使用 DI 和工厂模式

我个人更喜欢工厂模式方法,但您似乎反对必须将任何依赖项注入到您的类中。

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(); 
    }
}
于 2016-06-11T21:22:20.813 回答
0

(编辑:我刚刚意识到这实际上并没有返回另一个 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 类中需要这个构造函数:

public class SomeDbContext
{
    public SomeDbContext() : base("name=Prod")
    {
    }

    // EFfort unit testing ctor
    public SomeDbContext(DbConnection connection) : base(connection, contextOwnsConnection: true) {
        Database.SetInitializer<SolrDbContext>(null);
    }
}

但这意味着 repo 完全不知道特殊的瞬态连接:

public class SomeRepository
{
    public void SomeMethodName()
    {
        using (var context = new SomeDbContext())
        {
            // self-contained in repository, no special params
            // and still calls the special test constructor
        }
    }
}
于 2016-06-18T18:44:30.213 回答