Adventures in Testing with Mocks

I have recently gotten the mock testing bug. The biggest driving force to do this is that I find some things just too hard to test: in two cases I have to interact with the filesystem, and in another case I have to deal with third party Javascript UIs. I am trying it out in 2 different projects right now. So far I have played with Rspec with ruby, jsMock with Javascript and jMock with Java.

Observation #1



Rspec is the most enjoyable of the three, and it has one convinence feature that neither of the other 2 has: you can mock individual methods of a objects while still leaving the other methods intact. So, for example:

class MyObject
    def do_this
       ...
       do_that
    end

    def do_that
       ...
    end
end

What you can do in Rspec is mock out the method do_that, but still leave do_this intact. Then what you do is call do_this and verify that the mocked out do_that was called. Below is how it's done:

my_object.should_receive(:do_that)
my_object.do_this

This is impossible with jMock, as far as I can tell, once you mock out an object, all of its methods are mocked out, you pretty much have to create another object to interact with the first object in order to do any kind of mock testing. With jsMock in Javascript, this is not the default behavior, but you can still do it very simply:

var control = new MockControl()
var mock = control.createMock(MyObject)
mock.expects().doThis().andStub(MyObject.prototype.doThis)
mock.expects().doThat()
control.verify()

The magic happens on line 3 which replaces the doThis() method of the mock with the real doThis() method coming from MyObject's prototype(If you don't know that a prototype is, watch Douglas Crockford's videos).

Observation #2

Mockist testing in Java really sucks compared to Ruby, this is because you have to create a interface for everything single method that you want to mock independently. This causes interface-iitis(as promoted by the spring people and practiced my the eclipse people), which I really detest.

Lessons Learned for Now

There are things that are not that easy to test still with mocks. This is especially true for Java. What I did with Java was extract 3 or 4 interfaces just so that I could test them, but there are methods that I wish to against each other in the same class independently but just don't want to extract yet another interface, for that I really don't know what to do, maybe I'll just have to do that as an integration test.

Testing with rspec is a lot better. There are some things that I am still not sure how to do though, such as mocking a method and stubbing a return value at the same time. Javascript is not as nice. I had to refactor my Javascript to be more OO in order to test them: a procedural programming style does not yield well to mock testing.

I also reread Martin Fowler's essay: Stubs Ain't Mocks which gave me a lot of insight and reaffirmed some of the experiences I was having(the first read was quite confusing not having any hands on experience). I think at the end there's a balance somewhere about which approach to take(classic or mockist), and it depends on the situation.

More updates to come. I have just gotten started with this, so I am sure I'll learn more as I go.

blog comments powered by Disqus