Thursday
Jan222009
JMock vs EasyMock Smackdown

Lets see which of the two popular Java test object mocking tools is more straightforward. Cast your vote! (in comments)
with jMock | with EasyMock |
you need to import | |
import org.jmock.Expectations; | import static org.easymock.classextension. EasyMock.createMock; import static org.easymock.classextension. EasyMock.expect; import static org.easymock.classextension. EasyMock.expectLastCall; import static org.easymock.classextension. EasyMock.replay; import static org.easymock.classextension. EasyMock.verify; |
your test class needs to extend | |
MockObjectTestCase | TestCase |
in setUp() method | |
mockedThing = mock(SomeInterface.class) | mockedThing = createMock(SomeInterface.class) |
to set expectations | |
checking( new Expectations() {{ // this run does not throw one(mockedThing).run(); // expect an exception // expect multiple runs | // since run() returns void expect(mockedThing.run()); // or if the method returns non-void // expect an exception andThrow(new RuntimeException()); // expect multiple runs |
to put into replay mode | |
N/A | replay(mockedThing); // only after this call the mock is usable |
to use the mock in tests | |
RealThing realThing = new RealThing(mockedThing); // this will call the mocked thing at some point | RealThing realThing = new RealThing(mockedThing); // this will call the mocked thing at some point |
to verify mock | |
N/A | verify(mockedThing); // if you forget this, you will not know if the // expectations were fulfilled |
thread safe | |
??? | mockedThing is not thread-safe.... use this to make it so: makeThreadSafe(mockedThing, true); |
Reader Comments (5)
I vote for jMock. I hate the modal API of EasyMock, where it's all too easy to forget to put a mock in playback mode. Sure, jMock has some odd syntax, but it reads well once written.
Regarding your first comparison, why not just import all of the classextensions?
import static org.easymock.classextension.
EasyMock.*
I should also mention - this is all moot since Mockito is a better alternative to both frameworks mentioned here :) Check it out if you haven't yet.
I vote for EasyMock. The reason is the syntax is easier than JMock.
When you work in a large team with members at different levels. Choosing EasyMock is more reasonable.
As patient renter said, static import EasyMock.* instead of every method you will use (I find test cases specific enough domains to static import Asserts.* and EasyMock.* without having any confusion).
expect(someVoidMethod()) won't compile. You just have to call into your mocks for void methods.
In EasyMock, it's easier to understand if you think about how it works:
1. Call some methods into the proxy you created with createMock.
2. Perhaps define some things for those methods to return/throw.
3. replay [you're finished training it]
4. Call the code to test
5. verify [verify that what you expected happened in the proxy]
If you break down the order that things are happening in an EasyMock example, it becomes clearer when and why you need expectLastCall().
expect(myMock.add(1,2)).andReturn(3);
replay();
toTest.doSomething();
verify();
translates to:
1. call add method on myMock
2. call EasyMock.expect(T) [T is the return type of your add method]
3. call IExpectationSetters.andReturn(T)
4. call EasyMock.replay()
5. call your code to test
6. call EasyMock.verify()
As you can see, expect(myMock.add(1,2)).andReturn(3) is just a fancy way of writing:
myMock.add(1,2);
expect(0).andReturn(3); //The 0 is arbitrary, what is important is that it is the correct type (int/Integer in our case)
Well, what happens when we have a void method?
expect(myMock.voidMethod());
Uh-oh, nothing to return to be a parameter for our expect.
Well, if we don't need to throw an exception, just call the void method and we'll still correctly train our mock.
myMock.voidMethod();
But if we need our mock to throw an exception?
expect(myMock.divide(1,0)).andThrow(new ArithmeticException()); //This works
expect(myMock.voidMethod()).andThrow(new RuntimeException()); //This does not work, again, no return value to be expect's parameter
THAT is why we need expectLastCall()
myMock.voidMethod();
expectLastCall().andThrow(new RuntimeException());