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());

}
© 2012 - 2023 · Home — Theme Simpleness