2

Consider the following service interfaces:

public interface IServiceA
{
    void DoSomething(string s);
    void DoSomething(string s, bool b);
}

public interface IServiceB
{
    void DoSomething();
}

The implementation of IServiceB depends on IServiceA like this:

public class ServiceB : IServiceB
{
    private IServiceA _serviceA;

    public ServiceB(IServiceA serviceA)
    {
        _serviceA = serviceA;
    }

    public void DoSomething()
    {
        _serviceA.DoSomething("Hello", true);
    }
}

Ie. the dependency is injected in the constructor.

Now consider a unit test for the DoSomething() method. I wish to assert that one of the overloaded DoSomething-methods in IServiceA is called, but following a general principle that unit tests shouldn't know too much about the internal workings of the method being tested, I wish to be agnostic about which of the two overloads is called. Consider the following unit test:

[TestFixture]
public class ServiceBTests
{
    [Test]
    public void DoSomething_CallsServiceA()
    {
        var serviceAMock = MockRepository.GenerateMock<IServiceA>();
        var service = new ServiceB(serviceAMock);

        service.DoSomething();

        // Problem: How to check if EITHER:
        serviceAMock.AssertWasCalled(s => s.DoSomething(Arg<String>.Is.NotNull, Arg<bool>.Is.Anything));
        // OR:
        serviceAMock.AssertWasCalled(s => s.DoSomething(Arg<String>.Is.NotNull));
    }
}

How can I assert that either one or the other of the two methods was called?

Tor Haugen
  • 19,509
  • 9
  • 45
  • 63
  • Hmm. Maybe my thinking is skewed here. I guess the unit test should ascertain that DoSomething() does excactly what it should. And while the internal workings of the method does not concern the unit test, knowing exactly what the method should do entails, perhaps, knowing exactly which overload should be called. Any opinions on this? – Tor Haugen Dec 08 '10 at 11:38

1 Answers1

5

You could manually set a boolean flag like so:

[TestFixture]
public class ServiceBTests
{
    [Test]
    public void DoSomething_CallsServiceA()
    {
        var serviceAMock = MockRepository.GenerateMock<IServiceA>();
        bool called = false;
        serviceAMock.Stub(
             x => x.DoSomething(Arg<String>.Is.NotNull, Arg<bool>.Is.Anything))
            .WhenCalled(delegate { called = true; });
        serviceAMock.Stub(x => x.DoSomething(Arg<String>.Is.NotNull))
            .WhenCalled(delegate { called = true; });

        var service = new ServiceB(serviceAMock);

        service.DoSomething();

        Assert.IsTrue(called);
    }
}

I don't think this very useful though. Unit tests are concerned with anything that is observable from outside of the component boundaries. Method calls to mocks are part of that. In other words, it is OK if you test for a specific overload being called. After all, there must be a reason why you use that overload and not the other one.

If you really want the unit test to remain ignorant of the implementation, you wouldn't be allowed to assert method calls on mocks at all. That would be a severe restriction on your ability to write tests.

Wim Coenen
  • 66,094
  • 13
  • 157
  • 251
  • 1
    Yes. You might have seen my comment above, it reflects a realization along those lines. So I have written my unit tests for specific calls after all. But thanks for the tip anyway. It might come in handy in special cases. – Tor Haugen Dec 08 '10 at 21:41
  • I stumbled across a very similar situation using NSubstitute. Couldn't you argue that it wouldn't matter which method was called, as long as the behavior was the same? Isn't behavior driven testing better most of the time? – julealgon Sep 02 '14 at 20:23