用于MVC应用程序单元测试的模拟实体框架

时间:2015-03-13 07:46:13

标签: asp.net-mvc entity-framework unit-testing mocking

我开发了一个带有实体框架[DB]的MVC应用程序。我没有使用Repository ORM直接在实体上处理CRUD操作。

现在我打算编写单元测试。

是否可以在不使用我的生产数据库的情况下模拟实体?

请建议模拟实体的最佳方法

1 个答案:

答案 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返回的实际对象。