我开发了一个带有实体框架[DB]的MVC应用程序。我没有使用Repository ORM直接在实体上处理CRUD操作。
现在我打算编写单元测试。
是否可以在不使用我的生产数据库的情况下模拟实体?
请建议模拟实体的最佳方法
答案 0 :(得分:3)
一种可能的方法是将现有的Entity Framework类包装在一个接口中。例如,您可以创建一个名为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
,并且可以在测试期间模拟界面。您可以为每个进行外部调用的Entity Framework类执行此操作,并且还允许您在使用DbContext
方法时添加额外的错误检查等。
我在Azure表/队列存储中使用了这种方法,它运行良好,但需要额外的编码才能包装真实对象。
更新#1:作为附注,我不会包装所有EF对象。相反,只是访问外部资源的那些。因此,如果I方法有一个类型为EF对象的参数,并且该对象只有一些属性,那么请在IDbContextAdapter
方法签名中包含该属性并且不要包装它(这也适用于返回值) )。
更新#2:更新了代码示例以说明UPDATE#1中的要点。请注意GetValidationErrors
方法如何不包装EF类型DbEntityValidationResult
,而只是返回从真实DbContext
返回的实际对象。