如何实现Moq的It.IsAny <T>()

And*_*ner 6 c# moq

对于C#的起订量,我就通过调试,并注意到It.IsAny<T>()刚刚编译到一定值时T,如Guid.EmptyGuidS,0 intS等

Moq如何区分an It.IsAny<T>和它编译的值?

Cla*_*sen 7

GitHub源代码为基础,真正匹配的是给定的类型谓词Predicate<T>(或者Func<T, bool>如果你喜欢):

value => value == null || typeof(TValue).IsAssignableFrom(value.GetType())
Run Code Online (Sandbox Code Playgroud)

它检查是否value为null,或者是否与使用Type.IsAssignableFromvalueTValue参数类型相同.IsAny<TValue>

然后它返回default(T)类型的值以允许模拟方法正确匹配签名.正如DavidH所指出的,你不能对值类型使用null,这就是为什么使用default(T)作为泛型返回值的首选.

  • 因为您不能为值/结构类型返回null. (6认同)
  • 为什么它返回`default <T>`? (3认同)

Jep*_*sen 6

我们Setup在Moq嘲笑时使用的lambda 不是通常的代表,它们是表达树.该It.Is<>方法只是一个占位符.它实际上不一定被称为.如果它返回default(T)或只是抛出一个NotSupportedException或其他东西并不重要.让我举个例子:

interface IMyFace
{
  void MethodToTest(object obj);
}

static class Test
{
  public static void Main()
  {
    Setup<IMyFace>(x => x.MethodToTest(null));
    Setup<IMyFace>(x => x.MethodToTest(MyAnyA<object>()));
    Setup<IMyFace>(x => x.MethodToTest(MyAnyB<object>()));
  }

  public static TArg MyAnyA<TArg>()
  {
    // never runs
    return default(TArg);
  }
  public static TArg MyAnyB<TArg>()
  {
    // never runs
    return default(TArg);
  }

  public static void Setup<T>(Expression<Action<T>> expr) where T : class
  {
    Console.WriteLine("The expr was: " + expr);
  }
}
Run Code Online (Sandbox Code Playgroud)

不太有趣,但它应该表明,使用表达式树,Expression<...>您可以看到使用了什么方法,而不仅仅是返回的值.详细了解如何在MSDN,表达式树上检查表达式树.