【问题标题】:Mock Entity Framework For MVC Application Unit testingMVC 应用程序单元测试的模拟实体框架
【发布时间】:2015-03-13 16:41:22
【问题描述】:
我已经使用实体框架[DB] 开发了一个 MVC 应用程序。我已经直接在实体上处理了 CRUD 操作,而不使用 Repository ORM。
现在我打算写单元测试。
是否可以在不使用我的生产数据库的情况下模拟实体?
请建议模拟实体的最佳方法
【问题讨论】:
标签:
asp.net-mvc
entity-framework
unit-testing
mocking
【解决方案1】:
一种可能的方法是将现有的实体框架类包装在一个接口中。例如,您可以创建一个名为IDbContextAdapter 的接口并实现一个名为DbContextAdapter 的类。然后,这将实现接口并简单地将调用中继到真实的DbContext。
public interface IDbContextAdapter
{
IEnumerable<DbEntityValidationResult> GetValidationErrors();
int SaveChanges();
...
}
然后上课……
public class DbContextAdapter : IDbContextAdapter
{
private readonly DbContext _realContext;
public DbContextAdapter(DbContext context)
{
_realContext = context;
}
public IEnumerable<DbEntityValidationResult> GetValidationErrors()
{
return _realContext.GetValidationErrors();
}
public int SaveChanges()
{
_realContext.SaveChanges();
}
}
现在您可以在整个代码中使用IDbContextAdapter,并且可以在测试期间模拟接口。您可以为每个进行外部调用的实体框架类执行此操作,并且它还允许您在使用 DbContext 方法时添加额外的错误检查等。
我已经在 Azure 表/队列存储中使用了这种方法,它运行良好,但需要额外编码才能包装真实对象。
更新 #1:作为旁注,我不会包装所有 EF 对象。相反,只是那些访问外部资源的人。因此,如果我的方法有一个类型为 EF 对象的参数,并且该对象仅具有一些属性,则将其包含在您的 IDbContextAdapter 方法签名中,并且不要费心包装它(这也适用于返回值)。
更新 #2:更新了代码示例以说明更新 #1 中的要点。请注意 GetValidationErrors 方法如何不费心包装 EF 类型 DbEntityValidationResult,而是简单地返回从真正的 DbContext 返回的实际对象。