我希望拦截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
}
答案 0 :(得分:0)
您有两种可能的选择。使用工厂或通过面向方面编程(如PostSharp)
PostSharp是一个很棒的工具,可以实现最干净的拦截 可能(意味着您的类和对象生成没有变化 即使你不是你的工厂用于创建对象和/或 接口)但它不是一个免费的库。而不是创建代理 在运行时,它会在编译时注入代码,因此会更改您的代码 初始程序以无缝方式添加方法拦截。
.....
很酷的是,你不会改变你的其他任何东西 代码,因此仍然可以使用new关键字生成对象。
我个人更喜欢工厂模式方法,但你似乎不得不在你的类中注入任何依赖项。
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();
}
}
答案 1 :(得分: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);
}
}
但这意味着回购是幸福地没有意识到特殊的瞬态连接:
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
}
}
}