出于测试目的,我想创建一个自动生成的EF上下文类的模拟(DB first)。
为了做到这一点,我已经生成了一个匹配的接口,并使自动生成的类实现了这个接口(只需将接口添加到T4模板)。所以现在我的EF上下文如下所示:functions.php
IContext具有MyContext和DbContext具有的所有属性。
下一步是创建一个实现相同接口的模拟类。所以现在我也有:class MyContext : DbContext, IContext
。
现在针对有问题的部分:我的代码的一部分使用名为Configuration of DbContextConfiguration的DbContext属性(此属性允许我关闭"自动检测更改"功能)。问题是现在我需要为我的mock创建一个DbContextConfiguration实例,但是DbContextConfiguration只有内部构造函数,并且它没有实现任何接口。这意味着我无法直接创建它的实例,我无法继承它(感谢Microsoft)。
我已成功设法使用反射创建DbContextConfiguration实例,但不幸的是它无法使用。我可以提供有关此尝试的更多详细信息,但它就像是深入了解内部对象实例化的漏洞,我无法看到这种方法是如何工作的。
实体框架真的不可撼动,还是我可以做些什么?
答案 0 :(得分:3)
在您的特定情况下,将一个方法/属性添加到您的IContext似乎是一个更好的选择,切换AutoDetectChanges功能:
public interface IContext {
//....
bool AutoDetectChanges { get; set; }
bool LazyLoadingEnabled { get; set; }
//etc..
}
你甚至可以把它包装到一些配置类:
public interface IContext {
//....
IContextOrmOptions Options { get; set; }
}
public interface IContextOrmOptions {
bool AutoDetectChanges { get; set; }
bool LazyLoadingEnabled { get; set; }
//etc..
}
//real implementation
public class EntityFrameworkContextOrmOptions : IContextOrmOptions {
private DbContext _dbContext;
public EntityFrameworkContextOrmOptions(DbContext dbContext) {
dbContext = _dbContext;
}
public bool AutoDetectChanges {
{ get { return _dbContext.Configuration.AutoDetectChangesEnabled; } }
{ set { _dbContext.Configuration.AutoDetectChangesEnabled = value; } }
}
}
不幸的是,这种方法有点打破了系统的ORM不可知性,也许有一种方法可以避免这种代码?
如果您想要模拟.Entry()
方法,这也会让您遇到问题,因为它为您提供了很多方法 - 但这无论如何都很难。
答案 1 :(得分:0)
它比你想做的要简单得多,当然DbContext可以被嘲笑。这是一篇很好的文章/教程:
https://msdn.microsoft.com/en-us/library/dn314429.aspx
假设您使用的是EF 6 +