Skip to content
Jul 28 / davidalpert

Using Rhino.Mocks WhenCalled(…) – remember to Return(…)!

Today I was working with a repository that looked like this:

public interface IRepository
{
    ...
    IQueryable<T> Get<T>();
    IQueryable<T> Get<T>(Expression<Func<T, bool>> predicate);
    ....
}

This allows consumers of the repo to shorten

var result = repo.Get<IWidget>().Where(w => w.Price > 10.00m);

to this:

var result = repo.Get<IWidget>(w => w.Price > 10.00m);

Not complicated but sure convenient when you are issuing a lot of queries against the repo.

In one test I had mocked the repo like so:

List<IWidget> fakeWidgets;

IRepository mockRepo = MockRepository.GenerateMock<IRepostory>();

mockRepo.Expect(r => r.Get<IWidget>()).Return(fakeWidgets.AsQueryable());

What this does is create a fake IRepository instance and then set it up so that when any consumer calls Get<IWidget() it returns our collection of fakeWidgets.  The AsQueryable() call on the end is to transform our fake List<IWidget> into the IQueryable<IWidget> returned by Get<IWidget>().

That worked great for calls like

var result = repo.Get<IWidget>().Where(… some predicate …);

but failed, predictably, with a NullReferenceException on calls like

var result = repo.Get<IWidget>(… some predicate …);

So here’s how I first set up an expectation that would delegate this predicate:

List<IWidget> fakeWidgets;

IRepository mockRepo = MockRepository.GenerateMock<IRepostory>();

mockRepo.Expect(r => r.Get<IWidget>()).Return(fakeWidgets.AsQueryable());

mockRepo.Expect(r => r.Get<IWidget>(Arg<Expression<Func<IWidget, bool>>>.Is.Anything))
        .WhenCalled(invocation =>
        {
            var predicate = invocation.Arguments.First() as Expression<Func<IWidget, bool>>;
            invocation.ReturnValue = mockRepo.Get<IWidget>().Where(predicate);
        });

Don’t let the angle-brackets scare you; Arg<Expression<Func<IWidget, bool>>>.Is.Anything is simply Rhino Mocks’ way of saying accept any argument which looks like a function that takes an IWidget and returns a bool.

Then magic of the WhenCalled(…) method in line 8 is that it lets you manipulate a model of the actual method invocation which you are expecting. In this case on line 10 I’m grabbing that predicate argument matched in line 7 and then, on line 11, applying the predicate to the previously mocked Get<IWidget>() and stuffing it back into the method invocation as the actual ReturnValue.

What this effectively accomplishes is to make a call to the Get<IWidget>(predicate) method on that mocked IRepository act like a call to the Get<IWidget>() that has had the predicate applied.

Method … requires a return value or an exception to throw.

When I ran my test I got this error:

Method ‘IRepository.Get<IWidget>(anything);’ requires a return value or an exception to throw.

It took me a while to make sense of this message.

I had set the ReturnValue of the MethodInvocation passed to WhenCalled(…) so I figured Rhino Mocks knew the return value and I could safely drop the explicit Return(…) call that ends line 5

So what was going on?

Return(…) is required

Turns out Google and this post by Carlos Mendible came to my rescue.

The important part is that Rhino Mocks requires a Return(…) call at the end of an Expect(…) chain in order to determine the type of the return result.

Hence my delegating WhenCalled(…) code had to look like this:

mockRepo.Expect(r => r.Get<IWidget>(Arg<Expression<Func<IWidget, bool>>>.Is.Anything))
        .WhenCalled(invocation =>
        {
            var predicate = invocation.Arguments.First() as Expression<Func<IWidget, bool>>;
            invocation.ReturnValue = mockRepo.Get<IWidget>().Where(predicate);
        })
        .Return(Enumerable.Empty<IWidget>().AsQueryable());

Now my calling client that used the shorter syntax behaves exactly as expected.

Leave a comment