Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Beyond Mocks – the Partial

It’s a litlte easy to get carried away with mocking when you first start doing it in conjuction with unit tests. Mocks are unbelivably flexible/powerful. However, to get the most out of them, you really need to be able to inject your mock into the class you’re testing. Conincidentaly trying to leverage mocks in your code will lead you to the first tangible benefit of unit testing – you’ll notice how tightly coupled your code is (i.e., impossible to test) and learn a wonderful aresenal of strategies to help you write better code.

There comes a point though where injection just doesn’t make a whole lot of sense for anything _but_ testing and even then the value might not be that evident. Let’s see how we can use RhinoMock’s Partials to solve the problem. Take for example an LoginHttpHandler that looks something like:

public void ProcessRequest(NameValueCollection parameters)
{
   string userName = parameters["username"];   
   string password = parameters["password"];
   User user = User.CreateFromCredentials(userName, password);
   //do something with our user
}

This code is impossible to unit test because the call to User.CreateFromCredentials can’t be mocked/faked/anything. The best we can do is mock whatever dependencies User.CreateFromCredentials has – but that’s just a nightmare not worth exposing ourselves to.

What we can do is use a partial instead of a mock. A mock is a dumb object that only records expectations and actuals. A partial on the other hand exposes all of the behavior of the class we’ve created a partial for – except those we’ve explicitly set expecations on. For example, if we rewrite the above code as:

public void ProcessRequest(NameValueCollection parameters){
   string userName = parameters["username"];
   string password = parameters["password"];
   User user = GetUser(userName, password);
  //do something with our user
}
public virtual User GetUser(string userName, string password)
{
   return User.CreateFromCredentials(userName, password);
}

We can use a  partial to write a useful unit test (well, there isn’t much to test for, but you get the idea):

[Test]
public void LoginHandlerInteractsWithUser()
{
   MockRepository mocks = new MockRepository();
   LoginHttpHandler handler = mocks.PartialMock();
   User fakeUser = new User();
   NameValueCollection nvc = new NameValueCollection();
   nvc.Add("userName", "un");
   nvc.Add("password", "pass");
   using (mocks.Record())
   {
      Expect.Call(handler.GetUser(nvc["userName"], nvc["password"])).Return(fakeUser);
   }
   using (mocks.Playback())
   {
      handler.ProcessRequest(nvc);
   }
   mocks.VerifyAll();
}

We create a partial of our LoginHttpHandler which behaves exactly like a new instance of it – except for those methods (like GetUser) which we’ve set an expectation on. Just like with a mock, if ProcessRequest called GetUser twice, we’d have to record that call twice. Unlike a mock however, if we didn’t, the 2nd call would call the real implementation of GetUser.

The only other thing to keep in mind is that the method you plan on mocking must be virtual – this allows  RhinoMocks to override the method and do it’s own thing (implement the record/playback logic).

In my recent trip down Java land, I actually have a hell of a problem doing this seemingly simple thing. I tried a number of mocking frameworks, eventually settling on EasyMock but the amount of work needed to set up partials was insane. If I missed something, I’d love to know about it.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

6 Responses to Beyond Mocks – the Partial

  1. Rob Kitson says:

    @Gil,

    Testable as-is is not necessarily a good thing since you can get away with more tightly coupled code.

    As Derik mentioned earlier, in this case the testing is showing us where the code is highly coupled and, although refactoring that method call out into another method doesn’t help with that, it does shine a bright light on that dependency.

  2. Gil Zilberfeld says:

    @Karl,

    As you said, the method you refactored should be virtual because Rhyno needs it to be so for mocking it. So you’re changing your code just so you can use the tool.

    Typemock Isolator allows you to mock static methods. In that case your original code is testable as-is.

  3. Rob Kitson says:

    @Lex,

    Partialmocks are used for testing part of a class, not an interface. They are useful when you want to test the methods in an abstract class and need to provide return values from abstract methods.

    I guess I’m wondering why you would use a partialmock with an interface? Unless you are trying to find the golden hammer of mock types, which doesn’t exist.

  4. @Karl,

    What you are really showing here more so than the use of partials is how testing/mocking makes you separate out dependencies/pain points in your code. And this can lead to much cleaner code and more reliable tests.

    Nice post.

  5. @Lex,

    correct. And if u take a look at what a partial is actually doing it makes sense that it only works on objects. This is because you still want some method/properties to execute as normal.

  6. Lex Y. Li says:

    Partial mock is a nice addition, but I have just found that RhinoMocks cannot create a partial mock object for interfaces. This means every time I need a mock object of certain interface, I must provide all information. Because of this issue, I continue to use NMock 2 in my projects.