如何模拟DbSet的Include方法?

5

我在我的仓库中有以下方法

public IQueryable<T> QueryWithInclude(String include)
        {
            return _dbSet.Include(include);
        }

我该如何使用Moq模拟一个方法?我似乎找不到正确的方法。

例如,我可以使用以下方式:

public IQueryable<T> Query()
            {
                return _dbSet;
            }

mockrepository.Setup(_ => _.Query()).Returns(foo.AsQueryable()); 

此外,如果对这种方法的嘲笑最终变得困难,那么考虑替代实现或解决方法是否明智?
1个回答

3
只要你的抽象化返回 IQueryable(像DbSet),那么你可以创建自己的Include扩展到IQueryable中。您的代码将自动调用您的新Include扩展方法。当在返回DbQuery的抽象上使用时,它会调用正确的Invoke,否则如果它是一个IQueryable实例,则不执行任何操作。添加此新扩展方法意味着您当前的代码应该可以编译而无需更改。
如下所示:
    /// see: http://msdn.microsoft.com/en-us/library/ff714955.aspx
    ///     
    /// The method has been modified from version that appears in the referenced article to support DbContext in EF 4.1 ->
    /// 
    /// </summary>
    public static class ModelExtensions {
        public static IQueryable<T> Include<T>
                (this IQueryable<T> sequence, string path) where T : class {
            var dbQuery = sequence as DbQuery<T>;
            if (dbQuery != null) {
                return dbQuery.Include(path);
            }
            return sequence;
        }
    }

如果您的单元测试使用了一个假的列表,那么Include将不会有任何作用。
但是我必须补充一点,关于为什么模拟EntityFramework是不好的和毫无价值的,存在着强烈的观点。如果您还没有看到这些观点,那么检查一下可能是值得的。

如果我使用你的方法,那么我的单元测试将需要引用 EF。我有单独的集成测试来测试 EF 相关内容。你有什么想法? - ashutosh raina
在您当前的设计中,您是如何避免在测试存储库层时引用EF程序集的? - Quinton Bernhardt
当我测试存储库时,EF的引用存在,但在测试服务层时不存在。对于服务层,我应该模拟我的存储库吗?还是我理解错了? - ashutosh raina
如果你想要别人给出意见,你可以将你的代码发布到CodeReview上。 - Quinton Bernhardt
我会将它发布到Code Review上,实际上当我开始时我确实请求了一些反馈。 当我达到更加功能完善的阶段,我将在那里请求正式审查。 - ashutosh raina
我不能告诉你应该做什么或不应该做什么… 我向你展示的是如何将Include ext方法移动到IQuerable <T>接口上,这样在测试期间,您可以使用虚假的IQueryable <T>存储库,在实际代码中使用DbQuery <T>。 - Quinton Bernhardt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接