سؤال

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

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

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.

My question is: is this a bug in FakeItEasy or am I doing something wrong?

هل كانت مفيدة؟

المحلول

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.

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);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top