Saturday, July 25, 2009

Rhino Mocks Out Ref Parameters

I started playing with Rhino Mocks recently. Yes, I'm late to the game. And yes, that game is great. If you've made it to this post I'm obviously preaching to the choir, so let's get to it.

I ran across a need to mock up an out parameter today. For the context of this article that would be a ByRef parameter to all you VBers. What to do? Well, it turns out to be a very simple task.

I have several repository methods in a little project of mine that read paged data. I like to return the total number of records in the same query from the database and so I use an out parameter in my repository methods. The methods look something like this:

public IList<RecordModel> ReadPaged(int pageNumber, int pageSize, out int recordCount);

This project of mine is written for ASP.NET MVC which, like every other ASP.NET MVC project, contains controllers. My controllers makes calls on the repositories and push the models returned into the ViewDataDictionary. The goal then is to create a stub for the IRecordRepository.ReadPaged() method that passes a content count, among other values, back to the controller so that the value may be pushed into the ViewDataDictionary and then validated in a unit test. That's a lot of talk for one small method call:

recordRepositoryStub
.Stub(m => m.ReadPaged(pageNumber, pageSize, out recordCount))
.OutRef(250)
.Return(records);

That call to OutRef(250) is what takes care of the out parameter. The method accepts a parameter array of objects. When the stub method is called by the controller, it populates its arguments into the out parameters in the order in which they are declared in the method signature.

Goal accomplished.

3 comments:

  1. And what about recordCount? As far as I understood, I have to declare it at the beginning of the test, like:
    int recordCount;
    ?

    ReplyDelete
  2. @HiveHicks

    That's a good point. And I did create a local place holder variable in the test to handle it.

    This is an old example though. The newer versions of Rhino Mocks handle this more gracefully, sort of. Instead of needing to pass a variable for every parameter, you can shortcut a little bit using the Args object.

    mock.Expect(x => x.Read(out Arg<int>.Out(100).Dummy))

    This both sets the return value as well as obviates the need for the local variable in the test. The expectations get a bit wordy, but it gets the job done.

    ReplyDelete
    Replies
    1. Thank you! I wasn't aware of the Dummy property used to satisfy the compiler.

      Delete