Arg<T>.Matches considered harmful?

I’m a fairly heavy user of RhinoMocks (although, given the choice, I’d rather use FakeItEasy).

One of my few complaints about it is the poor diagnostics when an assertion fails. One particularly dangerous combination is AssertWasCalled with Arg<T>.Matches:

public void A_test()
{
    var frobulator = MockRepository.GenerateStub<IFrobulate>();
    var cromulator = new Cromulator(frobulator);

    cromulator.Cromulate();

    frobulator.AssertWasCalled(f => f.Frobulate(Arg<Bar>.Matches(b => b.This == "something" && b.That == "somethingelse")));
}

The problem with this is that, if the assertion fails, you don’t know whether This or That (or both) was not what was expected.

One option is to assert each property separately:

public void A_slightly_better_test()
{
    var frobulator = MockRepository.GenerateStub<IFrobulate>();
    var cromulator = new Cromulator(frobulator);

    cromulator.Cromulate();

    frobulator.AssertWasCalled(f => f.Frobulate(Arg<Bar>.Matches(b => b.This == "something")));
    frobulator.AssertWasCalled(f => f.Frobulate(Arg<Bar>.Matches(b => b.That == "somethingelse")));
}

Alternatively, you can use Do to capture the object you want to inspect and then assert normally:

public void A_slightly_different_test()
{
    var frobulator = MockRepository.GenerateStub<IFrobulate>();
    Bar bar = null;
    frobulator.Stub(f => f.Frobulate(Arg<Bar>.Is.Anything))
        .Do((Func<Bar, string>)(b => { bar = b; return ""; }));
    var cromulator = new Cromulator(frobulator);

    cromulator.Cromulate();

    Assert.That(bar, Is.Not.Null);
    Assert.That(bar.This, Is.EqualTo("something"));
    Assert.That(bar.That, Is.EqualTo("somethingelse"));
}

And yes, both options are very ugly! Of course, what you should really do is use a custom matcher :)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s