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

How to wait for a call that takes a specific linq expression as an argument

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

我当前的代码如下所示

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

作为正在测试的代码中对和 this 的调用。

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))

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

When checking for argument equality, FakeItEasy uses object.Equals. If the type to be checked does not provide an adequate Equals method, you may have to use the That.Matches method described in Custom matching. Be particularly careful of types whose Equals methods perform reference equality rather than value equality. In that case, the objects have to be the same object in order to match, and this sometimes produces unexpected results. When in doubt, verify the type's Equals behavior manually.

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

一种方法是捕获表达式,然后询问它是否按照您的意愿行事(即,但接受 3 并拒绝非 3)。这很尴尬,但是很难比较谓词。我在 How to test for a Match with FakeItEasy on a predicate call?.

的回答中对此进行了更多讨论