如何等待以特定linq表达式作为参数的调用

时间:2017-07-14 12:34:52

标签: c# linq unit-testing expression fakeiteasy

我有一个电话,我想检查一下。此调用是一个将Linq表达式作为参数的方法。此表达式针对声明表达式的局部变量的id测试对象id。只有当Linq表达式相等时(使用局部变量替换)或者当linq表达式中使用的局部变量等于某个值时触发不可能触发时,如何才能轻松调用该触发器。

我目前的代码如下所示

   A.CallTo(() => SomeMethod.FindBy(item=> item.ItemId == 3)).MustHaveHappened(Repeated.Exactly.Once);

正在测试的代码中调用和。

SomeMethod.FindBy(item=> item.ItemId == id)

其中id是局部变量。这不起作用,因为在调用时不会替换id,并且我得到这样的错误。

SomeInterface`1[[someItem, someItemFolder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].FindBy(item=> (item.ItemId == 3))
  Expected to find it exactly once but found it #0 times among the calls:
    1: SomeInterface`1[UKHO.WeeklyRecipes.EFModels.EFModels.EfTag].FindBy(predicate: tag => (tag.TagId == value(UKHO.WeeklyRecipes.BusinessLayer.PreferenceQueries+<>c__DisplayClass2_0).id))

1 个答案:

答案 0 :(得分:3)

您看到此行为是因为FakeItEasy无法判断这两个表达式是否相同。当您提供对象作为参数约束时,FakeItEasy会尝试match the argument value exactly。在这种情况下,它意味着调用Expression的{​​{1}}方法。引用文档:

  

在检查参数相等时,FakeItEasy使用Equals。如果要检查的类型未提供足够的object.Equals方法,则可能必须使用Custom matching中描述的That.Matches方法。要特别注意Equals方法执行引用相等而不是值相等的类型。在这种情况下,对象必须是相同的对象才能匹配,这有时会产生意外的结果。如有疑问,请手动验证类型的Equals行为。

所以,基本上这意味着如果您创建了两个变量,一个包含表达式Equals而另一个item => item.ItemId == 3并使用item.ItemId == id进行比较,您会看到{{1结果,FakeItEasy也是如此。

一种方法是捕获表达式,然后查询它以查看它是否按您的喜好行事(即接受3并拒绝非3)。这很尴尬,但比较谓词很难。我在How to test for a Match with FakeItEasy on a predicate call?的答案中详细讨论了这一点。