【问题标题】:MustHaveHappened fails when called twice on the same object在同一个对象上调用两次时,MustHaveHappened 失败
【发布时间】:2012-10-13 01:32:32
【问题描述】:

给定以下被测类(以及相关的 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); }

这个测试方法(它试图验证 IBar.Test() 被调用了两次:一次是 Num = 1,一次是 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(),它会按预期工作。

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

【问题讨论】:

    标签: c# unit-testing fakeiteasy


    【解决方案1】:

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

    我不确定是否有针对此类情况的开箱即用支持,但您可以轻松实施解决方法(无需创建第二个 DTO 对象):

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-19
      • 1970-01-01
      • 2023-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多