Mock Testing

My head hurts. Have spent most of the afternoon starting to introduce mock object testing to my project. Not being ‘test infected’ to perfection I’ve been happily prototyping away without writing tests first for a couple of weeks, so introducing tests was going to be a chore anyway. I started off using cactus to write some server side tests as I’ve done in the past, however this path soon became very frustrating and slow.

Background: part of this project involves hooking up to the proprietary RMI interface of a 3rd party application in order to execute queries against their persisted object store and extract data for reporting purposes.

In order to test the classes that perform the queries using cactus requires BOTH an active instance of the 3rd party app, and for my app server to be running. Test data issues alone are enough to make me hurl. Ugh. Time to reach for mock objects, which I’ve been considering for some time.

First what I needed were mock object implementations of the 3rd party classes that are accessed by my code. I downloaded the nifty mockmaker plugin for eclipse. Apart from a few glitches with package names and imports, this works well at creating mock implementations ready for me to use.

Next I needed to refactor a lot of my methods to allow me to pass in the mock objects, rather than create them in the code with the new operator or call static factory methods. This lets me unit test those methods directly by setting up mock objects and passing them to the method. I kind of think of this as delegating the decision about actual implementation further up the chain of command. This was actually a big shift in thinking for me – one I’m not convinced about yet.

What I realised when setting up the mock objects for my test is just how unnecessarily over-dependant my design was on the 3rd party API. Every step would have involved more and more mock implementations and much more code to set them up to be called. What I needed to do was push more of those dependancies into my adapter layer, and simplify the interfaces as much as possible. This decoupling lets me reduce the amount of mock object code required dramatically, and I think my design is going forward really nicely.

What am I not completely comfortable with?

1. My adapter layer is quite heavily coupled to the 3rd party API. To mock test this layer would require a lot more work – I think I’ll have to test that using cactus and those test will be slow, data-dependant, and require an active instance to be running.

2. Instantiation of the objects that I’m mocking (outside of the 3rd party API) will HAVE to be done somewhere. My current strategy will be to place that instantiation within methods that don’t perform any other function than to perform instantiation (or call factory methods) and then pass responsibility to the tested method. Example:

public drink(Beer input, Urinal output) {

output.append(input.sumUnits());

}

public drink(Beer input) {

Urinal output = Urine.getUrinal();

drink(input, output);

}

The first method contains the actual implementation, but is ready to be passed a mock input and output for testing. The second method implements the interface that I want to be used by the rest of the system, as I don’t want to pass the urinal around.

Not sure I’m real happy about that either – will make refactoring a bitch. Another alternative might be to create some sort of environment Hashmap that contains the resources required and pass it around between methods. Would be interested to see other people’s strategies.

Leave a Reply

Your email address will not be published. Required fields are marked *