I just spent 2 hours debugging a problem that turned out to be tied to a lazy use of mocks.
In our core code we have a number of Mock objects defined for the key objects in our system. These are moderately functional mocks in that they support a fair bit of state. They are Good. They should be used.
I ran into an issue where I believed I was setting some state on a mock, and some later code appeared to be making the wrong decision based on the state of the mock.
It turns out that someone had needed a mock and didn't bother to see that a really good mock class already existed. So they created their own completely non-functional mock class, and they made it an inner class of the test class to boot. So, when I set the state on the mock I was actually calling a no-op method of the bad mock.
It took me a long time to come to grips with the fact that "my" mock object was misbehaving and not remembering state. I didn't think of this as an option because I had written that mock class and the state preserving code was trivial. So trivial that it could not be failing...unless I was actually using someone else' mock object.
Before writing a class, even a test related class you ought to look around a bit and see if the class already exists. In this case that's especially easy since the file will be named MockThing.java (or .groovy), and especially since Eclipse can find your class so easily.
Come to think of it, this new no-op mock class was probably created by Eclipse. Normally I'm a fan of tools making it easier to do things, but not when its the wrong thing to do!
It sounds like what you're calling a Mock is more like a Stub, or perhaps even a minimal emulator? My style is to keep Mocks very local to the relevant unit test so that there can be no confusion over where the behaviour is coming from.
ReplyDelete