Over the last few years, I’ve started expanding the places where I
use automated testing (both test driven development and behaviour driven
development, even though one would have to admit that in reality
there’s little difference between them). I had only every written very
simplistic JUnit tests for Java modules, but never really for the
greater overall project. This changed when I starting working on a Ruby
on Rails, where we were required to make extensive use of RSpec.
One
of the things I learned to appreciate was the heavy use of stubbing
(and expectations) that RSpec provided. Obviously, this was easier to do
for a dynamic language such as Ruby (ignoring all the other
shortcomings of the language itself).
When I started writing Java
applications again, I obviously wanted to be able to perform similar
tests with similar stubbings. To my dismay, the more pedantic amongst us
programmers somehow decided that partial mocking/stubbing was somehow a
truly terrible thing to do. I began reading all sort of justifications
for why it was bad, and how one should refactor the class being tested
in order to test it.
jMock and Mockito both adhered to this
belief, EasyMock seemed less stringent, but stubbing was overly
string-based (making refactorying later on a little annoying since tests
would fail for no other reason than renaming a method).
Following is an example of the EasyMock mechanism (as shown in their documentation)
ToMock mock = createMock(ToMock.class,
ToMock.class.getMethod("mockedMethod", null));
Unfortunately, all these folks fail to take into account the real world, and situation under which you code might not want to allow users to screw around with dependent objects. Here is a real example:
I
created a class which did a load of work (let’s call it FlowClass), and
part of this work was to use another class (let’s call it LoaderClass)
which started up operating system processes. I needed to test the flow
of FlowClass, but I didn’t want to start firing off all sorts of new
processes. Easily enough, I was able to move the instantiation of
LoaderClass into another method, but using something like jMock, how do I
prevent that one single method from causing processes to load? I
emphatically do not want the user to have to set
instance of LoaderClass (like a JavaBean property), because I needed to
keep strict control over the flow. The idea of having to introduce
potential erratic program behaviour simply in order to test is
completely unacceptable by any stretch of the imagination.
One
site I came across suggested subclassing FlowClass directly in the test
(even though, once more, the author makes all sort of claims of this
being evil but delicious). This did the job, but it seems like so many
lines of code to do nothing more than force a value to be returned. On
top of that, what if I wanted to check to make sure the method was even
ever called?
My needs eventually led me to create JavaStubs. It doesn’t do all the work that the other mocking frameworks do, but what it does
do is allow me to quickly and easily stub method, including capturing
exceptions for testing, and counting how many times they were called. I
tried to be as string-less as possible (thank goodness for Java
generics), and make it easily readable (much thanks to Mockito for
suggestions on that one).