Alex Rivera | Logout

Using Mockito to test abstract classes

Asked 2009-07-06T14:40:47.627
262

I'd like to test an abstract class. Sure, I can manually write a mock that inherits from the class.

Can I do this using a mocking framework (I'm using Mockito) instead of hand-crafting my mock? How?

Edit
Report

2 Answers

381

The following suggestion lets you test abstract classes without creating a "real" subclass - the Mock is the subclass and only a partial mock.

Use Mockito.mock(My.class, Answers.CALLS_REAL_METHODS), then mock any abstract methods that are invoked.

Example:

public abstract class My {
  public Result methodUnderTest() { ... }
  protected abstract void methodIDontCareAbout();
}
 
public class MyTest {
    @Test
    public void shouldFailOnNullIdentifiers() {
        My my = Mockito.mock(My.class, Answers.CALLS_REAL_METHODS);
        Assert.assertSomething(my.methodUnderTest());
    }
}

Note: The beauty of this solution is that you do not have to implement the abstract methods. CALLS_REAL_METHODS causes all real methods to be run as is, as long as you don't stub them in your test.

In my honest opinion, this is neater than using a spy, since a spy requires an instance, which means you have to create an instantiable subclass of your abstract class.

answered 2010-11-30T19:25:00.590
8

Try using a custom answer.

For example:

import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

public class CustomAnswer implements Answer<Object> {

    public Object answer(InvocationOnMock invocation) throws Throwable {

        Answer<Object> answer = null;

        if (isAbstract(invocation.getMethod().getModifiers())) {

            answer = Mockito.RETURNS_DEFAULTS;

        } else {

            answer = Mockito.CALLS_REAL_METHODS;
        }

        return answer.answer(invocation);
    }
}

It will return the mock for abstract methods and will call the real method for concrete methods.

answered 2009-07-15T20:38:54.840

Your Answer