如何最小化 IEnumerable<T> 以通过 Any() 条件检查

How to moq a IEnumerable<T> to pass Any() condition check

我在将 Moq 框架与 IEnumerable 一起使用时遇到了一些问题。我对模拟一个对象没有问题,但是我对模拟一个对象的 IEnumerableICollection 等等有些事情不了解。

例如:

[TestMethod]
public void UnitTest()
{
    var mockedExample = new Mock<IEnumerable<Class>>();

    var feedback = repository.SomeMethod(mockedExample.Object);
}

public void SomeMethod(IEnumerable<Class> input)
{
    if (input != null && input.Any())
    {
       //Stuff to do
    }
}

我的问题是检查输入时。我通过了 input != null 条件,但在 input.Any() 条件下出现错误。

如何设置模拟的 IEnumerable 以通过这两个条件?

提前致谢。

正如人们所说,我认为您在这里不需要模拟。我认为评论中提供了正确的选项。

但要回答您的问题:您应该指定 Any 方法的行为(在模拟中使用“setup”方法):

mockedExample.Setup(m => m.Any()).Returns(true);

但如果您尝试这样做,您将遇到此异常:

System.NotSupportedException: 'Unsupported expression: m => m.Any() Extension methods (here: Enumerable.Any) may not be used in setup / verification expressions.'

那是因为,“Any”不是 IEnumerable 接口的一部分(即使用法往往让您相信它是)。 “Any”是 IEnumerable 的扩展方法(所以基本上是一个简单的静态方法)。

public static bool Any<TSource> (this System.Collections.Generic.IEnumerable<TSource> source)

Source is here.

这基本上意味着您不能直接使用 Moq 模拟“Any”方法的行为。

但是,如果您检查“Any”方法中的内容:

public static bool Any<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw new Exception();
    }

    using (IEnumerator<TSource> e = source.GetEnumerator())
    {
        return e.MoveNext();
    }
}

当您的模拟对象的 GetEnumerator 被调用时,默认值被返回(因为您没有为它设置任何行为)它是“null”,因此“e.MoveNext()”调用失败。因此,您可以定义“GetEnumerator”行为并使其工作,但我真的认为评论中提供的解决方案更简单,并且会使代码更具可读性。