为什么我不能在变量中捕获FakeItEasy期望值?

我正在使用FakeItEasy伪造一些entity framework调用,以确保正确映射一堆奇怪的遗留数据库表。

我需要断言具有与特定DeliveryAddress匹配的Invoice的Customer正被添加到数据库中。

如果我这样做:

A.CallTo(() => db.Customers.Add( A.That.Matches( c => c.Invoices.First().Address == EXPECTED_ADDRESS) ) )).MustHaveHappened(); 

代码完美无缺。 我想通过在其他地方移动期望来简化语法,但是当我这样做时:

 var expected = A.That.Matches( c => c.Invoices.First().Address == EXPECTED_ADDRESS) ); A.CallTo(() => db.Customers.Add(expected)).MustHaveHappened(); 

测试失败。 FakeItEasy代码中发生了什么,这意味着期望表达式在内联时有效,但无法在变量中捕获并在以后重用?

答案是在Always place Ignored和A.CallTo里面的文档中 :

Ignored (和_ )和That匹配器必须放在A.CallTo调用内的表达式中。 这是因为这些特殊约束方法不返回实际的匹配器对象。 它们告诉FakeItEasy如何通过触发的特殊事件匹配参数,然后调用约束方法。 FakeItEasy只监听A.CallTo上下文中的A.CallTo

不过,我对“测试失败”感到惊讶。 你用的是什么版本? 从FIE 2.0.0开始,像你一样使用That 应该抛出一个exception

 System.InvalidOperationException : A.Ignored, A._, and A.That can only be used in the context of a call specification with A.CallTo() 

对于为什么期望表达式内联工作而不是变量(我正在研究它,将很快编辑答案!)而不是直接的答案。

但是,我不是.That.Matches的粉丝

如果不止一个,比赛可能会有点笨拙。 如果任何匹配失败, MustHaveHappened调用将抛出exception。 让我不知道失败发生在哪里。

我更喜欢这样做:

 Customer addedCustomer; A.CallTo(() => a.Add(A._)) .Invokes(c => addedCustomer = c.GetArgument(0)); //Individual Asserts on addedCustomer Assert.AreEqual(EXPECTED_ADDRESS, addedCustomer.Invoices.First().Address); 

布莱尔的回答是正确的。 我只是想建议一个解决方法:

 // Local function, requires C# 7 Customer ExpectedCustomer() => A.That.Matches( c => c.Invoices.First().Address == EXPECTED_ADDRESS)); A.CallTo(() => db.Customers.Add(ExpectedCustomer())).MustHaveHappened();