如何使用存储库模式伪造Entity Framework中的DbContext.Entry方法

Erw*_*ers 39 c# unit-testing entity-framework repository-pattern asp.net-mvc-4

因为我想对我的代码进行单元测试,所以我在MVC4应用程序中实现了存储库模式.我设法创建了一个Context Interface,一个假的Context,并System.Data.Entity.DbSet通过遵循这个代码使用a的假实现.

不幸的是,就像我面前的两张海报(这里这里),我没有设法嘲笑DbContext.Entry method.我使用此方法更新代码中的数据库条目,如下所示:

DbContext.Entry(order).State = EntityState.Modified;
Run Code Online (Sandbox Code Playgroud)

我还没有找到解决这个问题的方法,只有那些人说:

"这个代码单元测试的重点是什么?你伪造了Find方法,然后伪造DbEntityEntry并且没有真正的逻辑可以测试."

或者

在继续之前,请阅读链接和所有相关问题.(...)如果要测试存储库,请创建与真实数据库对话的集成测试.

这一切都很好,但仍然没有回答这个问题.我阅读了批评,我仍然想要这个Entry方法,所以我将能够使用假上下文并在我的单元测试中使用模拟对象.当然我也会使用集成测试,但它们并不像某些快速单元测试那么快.

我尝试一些实现时收到的错误是 Error 2 'Project.Models.Order' does not contain a definition for 'State' and no extension method 'State' accepting a first argument of type '[whatever return type I use]' could be found (are you missing a using directive or an assembly reference?)

我希望有人可以帮我制作一个假的DbContext.Entry方法.

Erw*_*ers 36

找到答案在这里通过"添加间接的附加级别"我们得到:

public void SetModified(object entity)
{
    Entry(entity).State = EntityState.Modified;
}
Run Code Online (Sandbox Code Playgroud)

DbContext.SetModified(entity)在我们的控制器中使用.


Dav*_*ave 5

为了解决这个问题,我添加了一个方法重载,并添加了一个过时的属性来查看原始方法的调用位置。

    public virtual void Entry<TEntity>(TEntity entity, Action<DbEntityEntry<TEntity>> action) where TEntity : class
    {
        action(base.Entry(entity));
    }

    [Obsolete("Use overload for unit tests.")]
    public new DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class
    {
        return base.Entry(entity);

        /** or **/

        throw new ApplicationException("Use overload for unit tests.");
    }
Run Code Online (Sandbox Code Playgroud)

那么你也能 DbContext.Entry(order, ent => ent.State = EntityState.Modified;