【问题标题】:LINQ fails when mocking IDbSet GetEnumerator模拟 IDbSet GetEnumerator 时 LINQ 失败
【发布时间】:2014-03-28 06:58:19
【问题描述】:

我正在尝试模拟 System.Data.Entity.IDbSet 以使其返回一些数据(在这种情况下只是一个空集合):

var mock = new Mock<IDbSet<Setting>>();
mock.Setup(x => x.GetEnumerator()).Returns(Enumerable.Empty<Setting>().GetEnumerator());
var myEnumerator = mock.Object.GetEnumerator();
var count = mock.Object.Count();

这里 myEnumerator 将有一个非空值,正如预期的那样,但 mock.Object.Count() 会抛出一个 ArgumentNullException

System.ArgumentNullException : Value cannot be null.
Parameter name: arguments
   at System.Linq.Expressions.Expression.RequiresCanRead(Expression expression, String paramName)
   at System.Linq.Expressions.Expression.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi)
   at System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ref ReadOnlyCollection`1 arguments)
   at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
   at System.Linq.Queryable.Count(IQueryable`1 source)

如果我用 IEnumerable 替换 IDbSet,它会按预期工作(计数为零)。为什么 IDbSet 没有像我预期的那样被嘲笑?

编辑

看起来 LINQ 尝试使用 IQueryable 接口,因为它有效:

var mock = new Mock<IDbSet<Setting>>();
var myQueryable = Enumerable.Empty<Setting>().AsQueryable();
mock.Setup(m => m.Provider).Returns(myQueryable.Provider);
mock.Setup(m => m.Expression).Returns(myQueryable.Expression);
mock.Setup(m => m.GetEnumerator()).Returns(myQueryable.GetEnumerator());
var count = mock.Object.Count();

【问题讨论】:

    标签: c# linq entity-framework moq


    【解决方案1】:

    事实证明 LINQ 有 IQueryable 的显式实现:

        public static int Count<TSource>(this IQueryable<TSource> source) { 
            if (source == null)
                throw Error.ArgumentNull("source"); 
            return source.Provider.Execute<int>( 
                Expression.Call(
                    null, 
                    ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)),
                    new Expression[] { source.Expression }
                    ));
        }
    

    实际上,LINQ 表达式如何将表达式转换为实体框架查询是很有意义的。

    所以我也必须模拟提供者和表达式:

    var mock = new Mock<IDbSet<Setting>>();
    var myQueryable = Enumerable.Empty<Setting>().AsQueryable();
    mock.Setup(m => m.Provider).Returns(myQueryable.Provider);
    mock.Setup(m => m.Expression).Returns(myQueryable.Expression);
    mock.Setup(m => m.GetEnumerator()).Returns(myQueryable.GetEnumerator());
    var count = mock.Object.Count();
    

    【讨论】:

      【解决方案2】:

      你应该改变

      mock.Setup(m => m.GetEnumerator()).Returns(myQueryable.GetEnumerator())
      

      mock.Setup(m => m.GetEnumerator()).Returns(myQueryable.GetEnumerator)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-13
        • 2016-06-27
        相关资源
        最近更新 更多