【问题标题】:How to mock Include method of DbSet?如何模拟 DbSet 的 Include 方法?
【发布时间】:2013-01-13 09:13:55
【问题描述】:

我的存储库中有以下方法

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

如何模拟我正在使用 Moq 的这种方法。我似乎找不到正确的方法。

例如我可以为

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

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

另外,如果模拟这种方法最终变得很困难,那么考虑替代实现/变通方法是否明智?

【问题讨论】:

    标签: c# unit-testing nunit moq


    【解决方案1】:

    只要您的抽象返回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;
            }
        }
    

    因此,如果您的单元测试使用虚假的 IQueryable 列表,则 Include 将不会执行任何操作。

    我必须补充一点,对于为什么模拟 EntityFramework 是不好的和毫无价值的,我有强烈的意见。如果您还没有看到它们,可能值得一试。

    【讨论】:

    • 如果我使用你的方法,那么我的单元测试需要引用 EF。我有单独的集成测试来测试 EF 的东西。想法?
    • 在您当前的设计中,如何避免在测试存储库层时引用 EF 程序集?
    • 当我测试存储库时,对 EF 的引用在那里,但在我测试服务层时没有。对于服务层,我不应该模拟我的存储库吗?还是我想错了?
    • 如果您希望有人发表意见,您可以随时将您的代码发布到 CodeReview。
    • 我会把它发布到 Code Review 上,事实上,当我开始做这个的时候,我确实要求过一些反馈。当我达到更实用的阶段时,我会在那里要求进行正式审查。
    猜你喜欢
    • 1970-01-01
    • 2017-08-24
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-01
    • 2021-12-31
    • 1970-01-01
    相关资源
    最近更新 更多