当在同一对象上调用两次时,MustHaveHappened失败 [英] MustHaveHappened fails when called twice on the same object

查看:116
本文介绍了当在同一对象上调用两次时,MustHaveHappened失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下正在测试的类(以及相关的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆