6

对于这个问题,考虑(创建)界面:

public interface ITestMe
{
  string TakeInt64(long x);
}

然后运行以下代码:

public void Test()
{
  var mock1 = new Mock<ITestMe>(MockBehavior.Strict);
  Expression<Func<ITestMe, string>> expr1 = x => x.TakeInt64(2);
  Console.WriteLine(expr1);
  mock1.Setup(expr1).Returns("OK");
  var s1 = mock1.Object.TakeInt64(2L); // OK

  var mock2 = new Mock<ITestMe>(MockBehavior.Strict);
  Expression<Func<ITestMe, string>> expr2 = x => x.TakeInt64(DateTime.Today.Year / 1000);
  Console.WriteLine(expr2);
  mock2.Setup(expr2).Returns("OK");
  var s2 = mock2.Object.TakeInt64(2L); // OK

  var mock3 = new Mock<ITestMe>(MockBehavior.Strict);
  Expression<Func<ITestMe, string>> expr3 = x => x.TakeInt64((int)(DayOfWeek)Enum.Parse(typeof(DayOfWeek), "Tuesday"));
  Console.WriteLine(expr3);
  mock3.Setup(expr3).Returns("OK");
  var s3 = mock3.Object.TakeInt64(2L); // OK

  var mock4 = new Mock<ITestMe>(MockBehavior.Strict);
  Expression<Func<ITestMe, string>> expr4 = x => x.TakeInt64(GetInt32());
  Console.WriteLine(expr4);
  mock4.Setup(expr4).Returns("OK");
  //var s4 = mock4.Object.TakeInt64(2L); // MockException, All invocations on the mock must have a corresponding setup.

  var mock5 = new Mock<ITestMe>(MockBehavior.Strict);
  Expression<Func<ITestMe, string>> expr5 = x => x.TakeInt64(int.Parse("2"));
  Console.WriteLine(expr5);
  mock5.Setup(expr5).Returns("OK");
  //var s5 = mock5.Object.TakeInt64(2L); // MockException, All invocations on the mock must have a corresponding setup.

  var mock6 = new Mock<ITestMe>(MockBehavior.Strict);
  Expression<Func<ITestMe, string>> expr6 = x => x.TakeInt64(GetInt32() + 0);
  Console.WriteLine(expr6);
  mock6.Setup(expr6).Returns("OK");
  var s6 = mock6.Object.TakeInt64(2L); // OK

  var mock7 = new Mock<ITestMe>(MockBehavior.Strict);
  Expression<Func<ITestMe, string>> expr7 = x => x.TakeInt64(1 * int.Parse("2"));
  Console.WriteLine(expr7);
  mock7.Setup(expr7).Returns("OK");
  var s7 = mock7.Object.TakeInt64(2L); // OK
}

static int GetInt32()
{
  return 2;
}

在所有七种情况下,我们都创建了一个表达式树,其中TakeInt64得到一个int( Int32) 而不是long( Int64)。然而,众所周知,表达式树中存在隐式转换(编译器为我们转换常量的地方除外)intlongexpr1

案例s4s5以上怎么行不通?奇怪的是,正如您所看到的,如果我们在 case和中添加0或相乘,那是否有效(即使类型仍然是,隐式转换为)?1s6s7intlong

由于案例,请在 3000 年前回答expr2

4

1 回答 1

2

我认为这是 Moq 中的一个错误。相关代码在MatcherFactory. 具体来说,Convert从表达式中删除了,以便可以进一步检查它。当剩余的最上面的表达式节点是一个方法调用时,这个节点是惰性计算的。当剩余的表达式不是方法调用时,整个表达式(包括Convert!)都会被急切地求值。

这意味着对于惰性求值,比较是在没有Convertand object.Equals(2, 2L)is的情况下完成的false。但是通过热切评估,Convert会考虑到,因此您的代码可以正常工作。

我已经尝试解决这个问题,这似乎为我解决了这个问题。

(哇,我差点以为我来不及了。)

于 2013-09-18T17:56:27.053 回答