Tuesday, April 8, 2008

Mocking - pros and cons

Ok, so what is a mock? Simply saing, it's an object which behaves in a way *we* tell it to. Surely you can think of some advantages of such an object. Let's say we have class Gather with two methods: fetch_from_net and do_simple_task and the seconds uses the first. Let's say that fetch_from_net returns a string. We may want to test our methods (in fact we *should* do it ;).

Tests for do_simple_task method would generate some internet traffic because they would use fetch_from_net. Assuming it's already tested we may prevent this with *mocking* the method.


def test_simple_method
gather = Gather.new
gather.expects(:fetch_from_net).returns("some string")
out = gather.do_simple_task
# asserts for out should go probably here
end


Ok, we *told* gather object that when someone invokes :fetch_from_net (expects(:fetch_form_net)), it should return "some_string" instead of doing it's usual job.

It's useful. But...

There is one gotcha. While you develop your app you surely change some things... your methods, arguments they take. When fetch_from_net changes it's argument list. You change the unit test but you somehow forget the functional one. Why? Because it *passes*. It passes because you told the object in it that it expects some method (and it got one obviously) and that it should return something (which is probably a valid "thing" since you know what it should return because you tested it in unit test).

You can fix this by specifing that you expect some method with specific arguments, but then you must think about it all the time and it gets annoying sometimes.

One really useful mock method is "raises". It's a great way to force object to raise an exception. If you are testing a case when you know the exception will be raised, you can tell object to raise it on specific method and then you can test the logic which takes care of this exception. No fake args are needed to manually create this exception.

Concluding: mock-approach is ok, but you have to take precautions or else you may and up with broken functionality and green tests (and that's *really* dangerous!). Also, mind that sometimes it's quite hard to come up with a good, working mockup or you may need to mock many objects.

0 comment(s):