在同一对象上调用两次时,MustHaveHappened失败

给定以下测试类(以及相关的DTO类和接口):

public class Foo { private readonly IBar _bar; public Foo(IBar bar) { _bar = bar; } public void DoStuff() { var dto = new DTO(); dto.Num = 1; _bar.Test(dto); dto.Num = 2; _bar.Test(dto); } } public class DTO { public int Num { get; set; } } public interface IBar { void Test(DTO dto); } 

而这个测试方法(试图validationIBar.Test()被调用两次:一次使用Num = 1,一次使用Num = 2):

 public void TestMethod1() { var bar = A.Fake(); var foo = new Foo(bar); foo.DoStuff(); A.CallTo(() => bar.Test(A.That.Matches(x => x.Num == 1))).MustHaveHappened(); A.CallTo(() => bar.Test(A.That.Matches(x => x.Num == 2))).MustHaveHappened(); } 

第一个’MustHaveHappened’调用失败。 我发现这是因为两次调用IBar.Test()时使用的DTO都是同一个实例。 如果我更改代码以使用两个不同的DTO调用IBar.Test(),它将按预期工作。

我的问题是:这是FakeItEasy中的错误还是我做错了什么?

这是正确的行为,而不是错误。 FakeItEasy使用参数记录调用,但它不会在调用期间存储参数的内部状态 – 它只是存储参数本身的引用/值。 最后,在validation阶段, DTO对象的当前状态是Num等于2的状态,这就是FakeItEasy将validation的状态。

我不确定是否有这种情况的开箱即用支持,但您可以轻松实现此方法(不创建第二个DTO对象):

 var bar = A.Fake(); var foo = new Foo(bar); var expectedNumValues = new [] { 1, 2 }; var actualNumValues = new List(); // Whenever a call to IBar.Test is made, store DTO.Num in list A.CallTo(() => bar.Test(A.Ignored)).Invokes( fakeCall => { var dto = (DTO) fakeCall.Arguments[0]; actualNumValues.Add(dto.Num); } ); foo.DoStuff(); // this verifies that both collections contain same elements at same positions CollectionAssert.AreEqual(expectedNumValues, actualNumValues);