Diving in to Mock Objects

A new consulting gig I just started last week has a team who is interested in diving deep into Mock Objects as a testing philosophy.  As such, I’ve spent some time reacquainting myself with Mocking after having passed on it several years ago.

My chief complaint, as the doctors say, was that Mocking introduced an unnecessary level of complexity to your testing code.  My secondary complaint was that it broke encapsulation by giving your test code too much insight as to the expected implementation of your classes, what with all the .expect()s and .will()s floating around.  It’s like washing the family car with your Dad hovering over your shoulder, telling you the right way to use the sponge.  As long as it’s clean at the end, who cares?

In a nutshell, this is the argument over state-based vs. behavioral testing.  In state-based testing, you just want Car.IsClean() to return true.  In behavioral testing, you want Sponge.Wipe() to be called 137 times, and Hose.Spray() to be called 22 times.

Call me a keen proponent of state-based testing.

There are a couple areas where Mocking can get around very real weaknesses in state-based testing; for example, anything to do with nondeterministic behavior.  The authors of this paper, “Mock Roles, Not Objects”, conveniently use caching as a way to explore Mocking, and it make sense.  It would be hard to test caching to that level of detail without either (a) Mocks or (b) exposing a lot of guts of the implementation just to hang test hooks off of.

What’s your experience with Mocking?  Any best practices to relate?

Advertisements

1 Response to “Diving in to Mock Objects”


  1. 1 Wes Maldonado June 16, 2008 at 7:13 am

    I tend to use mocks most when testing the behavior of a resources controlled by a collaborating object. Consider a model that should add itself to a search service when it is saved or updated, you could stub the search service creating the correct interface, implementation, etc. or you could verify the behavior of your model by using a mock. I believe the behavior is the most obvious way to test this and therefore I would use a mock. Here is an example using rspec:

    describe SafetyInspectionForm, “when saving” do
    it ” should add itself to the search service when saving” do
    search_service = mock(“search service”)
    search_service.should_receive(:add).once
    # imagine I set this up via injection or a public setter
    # e.g. form.search_service = search_service
    form.save!
    # search_service.verify implicitly called
    end
    end

    Compared to creating a stub to take the hits from my model, then interrogate it to determine if the behavior was correct by analyzing state I can just define my behavior and test it directly. I don’t use mocks very frequently but they are useful. They clearly indicate the intent of the test. Compare to a hand grown mock that we wrote in js spec.

    SomeModel.describe(‘model marked deleted’, {

    ‘should persist internals to google gears’ : function(){
    model = factory.new_model();
    internal_thing = model.get_internal_thing();
    internal_thing.save = function(){ room.save_called = true; }
    model.delete();
    value_of(internal_thing.save_called).should_be(true);
    }
    }

    Food for thought. I find that the first few days with mocks are frustrating because you feel like you are stuck fixing your “mock” while trying to discover the correct interface. This interface discovery is the important thing though. You can achieve similar results with lots of test driving, but then you would actually have to write the object you’re interested in working with and once code it put down in the editor most are reluctant to change it.


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





%d bloggers like this: