EasyMock for mere mortals
I've found, during my brief experience with EasyMock, that trudging
through the documentation makes it terribly difficult to get things
done. From my reading, I wrote a handful of tests which use the
reset()
, replay()
, verify()
dance. When I changed trivial things
in my implementation, all of my tests broke. "We expected you to call
uselessMethod()
but you didn't!"
Simply fulfilling an interface
Simply put, verify()
is overrated. It turns out that the majority of
what I want out of easymock is for it to override all of the
interface's methods with OperationNotSupported
exceptions, except
for a few precious methods, which I can provide a bit of
implementation. This is done by just simply not calling verify()
at
the end of the method. While you don't assert that X method was called
Y times, chances are, you really don't want to do that anyway. It ties
you terribly close to your implementation, making your tests brittle.
package com.justinlilly.examples; import static org.easymock.EasyMock.*; import junit.framework.TestCase; // Note: The examples were hand-typed and not compiled first. If you // find an error, let me know. Also, assume the classes not imported // are package private. public class SimpleTest extends TestCase { Result knownResult = new Result(5L); MyDataSource mockDataSource = createMock(MyDataSource.class); expect(mockDataSource.getRelevantData(anyObject(MyIdentifier.class))); replay(mockDataSource); ClassUnderTest cls = new ClassUnderTest(mockDataSource); Result result = cls.methodUnderTest(); assertEquals(knownResult, result); }
Capturing your input
Another useful thing where there aren't tons of detail is capturing easymock method input. In my particular case, I was writing and end-to-end test for a class which ended in a persist. I wanted to be sure the thing we were persisting actually got to the persist call without having to have the database involved at all. To do this, I mocked the database connection and captured the parameter that was passed to the persist call for later verification.
For this functional test, we'll mock out a sample API service, which we'll get an intermediate object from. This object will then be transformed somewhere in the internals of our class. We'll then assert that the object that finally makes it to the persist call has the relevant values from our intermediate object.
package com.justinlilly.examples; import static org.easymock.EasyMock.*; import junit.framework.TestCase; // Note: The examples were hand-typed and not compiled first. If you // find an error, let me know. Also, assume the classes not imported // are package private. public class CaptureTest extends TestCase { String knownName = "Test Name"; IntermediateObject intermediate = new IntermediateObject(knownName); MyDataSource mockDataSource = createMock(MyDataSource.class); MyApiService mockApiService = createMock(MyApiService.class); Capture<MyObject> capturedObject = new Capture<MyObject>(); expect(mockApiService.getIntermediateObject()).andReturn(intermediate); expect(mockDataSource.persistObject(capture(capturedObject))).andReturn(new MyObject()); replay(mockApiService, mockDataSource); ClassUnderTest cls = new ClassUnderTest(mockDataSource, mockApiService); cls.start(); MyObject captured = capturedObject.getValue(); assertNotNull(captured); assertEquals(knownName, captured.getName()); }