Search code examples
javaunit-testingeasymock

EasyMock - mocking abstract methods inherited from an interface


I'm having some difficulty with EasyMock (3.1) class mocking. This is supposedly suitable to mock partial class implementations, which, I figured, should be ideal to unit test abstract base classes while mocking out the missing method(s). Here's the pattern - an instantly recognizable classic...

public interface Interface {
    public void intfMethod();
}

public abstract class AbstractBase implements Interface {
    public void otherMethod() {
        // do some stuff we need to test...
        intfMethod();
    }
}

Now the test:

public class TestAbstractBase {
    AbstractBase testInstance;

    @Before
    public void setUp() {
        testInstance =
            createMockBuilder(AbstractBase.class).addMockedMethod("intfMethod").createMock();
    }
    @Test
    public void testOtherMethod() {
        testInstance.intfMethod();  // expect this to be invoked on the mock...
        replay(testInstance);
        testInstance.otherMethod();
        verify(testInstance);
    }
}

EasyMock doesn't seem to like this. It throws:

java.lang.IllegalArgumentException: Method not found (or private): intfMethod
    at org.easymock.internal.MockBuilder.addMockedMethod(MockBuilder.java:78)
    at TestAbstractBase.setUp(TestAbstractBase.java:19)

Any ideas? I found a related question but it doesn't really do justice to its title...


Solution

  • Many thanks to @nhaldimann ; I'd overlooked this innocuous statement in the doc, namely that "abstract methods are conveniently mocked by default". So all the above needs is to remove the attempt to explicitly mock the interface method, as in:

    testInstance = createMockBuilder(AbstractBase.class).createMock();
    

    While researching this, I came across two other workarounds - although the above is obviously preferable:

    1. Use the stronger addMockedMethod(Method) API, as in:

      public void setUp() throws Exception {
          Method m = AbstractBase.class.getMethod("intfMethod");
          testInstance = createMockBuilder(AbstractBase.class).addMockedMethod(m).createMock();
      }
      
    2. Explicitly expose the intfMethod method in AbstractBase

    These two workarounds suggest that my initial issue is a bit of a bug on the EasyMock side of things. But since there's no need to mock that method in the first instance, we'll say this is "user (my) error".