我有一个电话,我想检查一下。此调用是一个将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))
答案 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?的答案中详细讨论了这一点。