Erik
11 Jun 2010

Partial mocks

Suppose we have this class:

public class Foo {
  int getA() {
    return 42;
  }
  int getB() {
    return 1;
  }
  int getC() {
    return getA() + getB();
  }
 }

This is of course a simplified version - in the real version the getA() and getB() are quite complex and require other dependencies to be set, the getC() method has of course a more complex formula that depends on getA() and getB().Now our task is to write a test for method getC(). What is the best way to do that? I would like to ignore the actual implementation of getA() and getB() and only test if the results of these methods are used correctly. We ended up with this:

import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class FooTest {
  @Test public void getC() {
    Foo foo = mock(Foo.class);
    when(foo.getA()).thenReturn(12);
    when(foo.getB()).thenReturn(11);
    when(foo.getC()).thenCallRealMethod();
    assertEquals(23, foo.getC());
  }
}

The code is quite short and relatively easy to read. But what slightly bothers me is that I am actually mocking the class that I am testing. While the thenCallRealMethod() clearly signals that I am actually calling the real method, it still feels slightly strange.Also the Mockito documentation recommends against using partial mocks unless you’re working on legacy code. This is not legacy code - I think the design is quite good - the logic of retrieving A and B is extracted to separate methods and getC() only deals with the calculation.An alternative would be to extend the Foo class inline and override getA() and getB() and return the required values. But this would yield a lot more lines of code and the readability would probably suffer.What do you think? Is this a good test? Can you suggest better alternatives?

Archived comments

Anton Arhipov 2010-06-11T22:01:53.603Z

the alternative you’ve listed is not better than using mockito, as extending Foo is actually the same as making a mock, but kind of an old-school way.no other suggestions though..

Our recent stories