当在同一对象上调用两次时,MustHaveHappened失败 [英] MustHaveHappened fails when called twice on the same object
问题描述
给出以下正在测试的类(以及相关的DTO类和接口):
Given the following class under test (and associated DTO class and interface):
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); }
这个测试方法(试图验证IBar.Test()是否被调用两次:一次使用Num = 1,一次使用Num = 2):
And this test method (which attempts to verify that IBar.Test() gets called twice: once with Num = 1 and once with Num = 2):
public void TestMethod1()
{
var bar = A.Fake<IBar>();
var foo = new Foo(bar);
foo.DoStuff();
A.CallTo(() => bar.Test(A<DTO>.That.Matches(x => x.Num == 1))).MustHaveHappened();
A.CallTo(() => bar.Test(A<DTO>.That.Matches(x => x.Num == 2))).MustHaveHappened();
}
第一个"MustHaveHappened"调用失败.我发现这是因为两次调用IBar.Test()所使用的DTO是同一实例.如果我更改代码以使用两个不同的DTO调用IBar.Test(),它将按预期工作.
The first 'MustHaveHappened' call fails. I have discovered that it is because the DTO used by both calls to IBar.Test() is the same instance. If I change the code to call IBar.Test() with two different DTO's it works as expected.
我的问题是:这是FakeItEasy中的错误,还是我做错了什么?
My question is: is this a bug in FakeItEasy or am I doing something wrong?
推荐答案
这是正确的行为,不是错误. FakeItEasy记录带有参数的调用,但在调用过程中不存储内部参数-它仅存储参数本身的引用/值.最后,在验证阶段,DTO
对象的当前状态是Num
等于2的状态,这就是FakeItEasy将对其进行验证的对象.
This is correct behavior, not a bug. FakeItEasy records calls with arguments, but it doesn't store arguments' internal state during the call - it simply stores reference/value of the argument itself. At the end, during your verification phase, DTO
object's current state is the one with Num
equal to 2, and that's what FakeItEasy will verify against.
我不确定此类情况是否有现成的支持,但是您可以轻松地实现此解决方法(而无需创建第二个DTO
对象):
I'm not sure whether there's out of box support for such cases, but you can easily implement workaround for this (without creating second DTO
object):
var bar = A.Fake<IBar>();
var foo = new Foo(bar);
var expectedNumValues = new [] { 1, 2 };
var actualNumValues = new List<int>();
// Whenever a call to IBar.Test is made, store DTO.Num in list
A.CallTo(() => bar.Test(A<DTO>.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);
这篇关于当在同一对象上调用两次时,MustHaveHappened失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!