Tuesday, May 19, 2009

How to mock protected method in Java

It's a very common situation when we call protected methods of a class from other methods in the same class. This article is about approach to testing such caller methods. We'll not discuss why a test is more robust and modular if it covers only functionality of enclosing method with assumptions that invoked methods satisfy their contracts. For more information about advantages of modular tests please refer to articles about TDD and JUnit testing in Java.

Let's first review some trivial example to be on the same page. There is EinsteinFormula interface below:

package com.intelrate.mockmethod;

public interface EinsteinFormula {
double kineticEnergy(double restMass, double velocity);

This interface states that we can get kinetic energy of some moving body if its rest mass and velocity are provided. Here is physical law describing the formula:


Take a look at implimentation:

package com.intelrate.mockmethod.impl;

import com.intelrate.mockmethod.EinsteinFormula;

public class EinsteinFormulaImpl implements EinsteinFormula {

static final double SPEED_OF_LIGHT = 2.99792458E8;

* Calculates kinetic energy for the given object.
* @param restMass object's mass
* @param velocity object's velocity
* @return kinetic energy according to Einstein formula

public double kineticEnergy(final double restMass, final double velocity) {
final double restEnegry = energy(restMass);
return restEnegry * (1 / Math.sqrt(1 -
(velocity * velocity) / (SPEED_OF_LIGHT * SPEED_OF_LIGHT)) - 1);

double energy(final double mass) {

As you can see, there are two meaningful methods in this class. It's quite clear how to test each of them from contract point of view but technically we don't want energy method to be called in a test for kineticEnergy because it is better to assume that energy works correctly when a test for kineticEnergy runs.

If energy method was in interface we could easily mock it using nested class as it is described at the end of article about TDD but problem here is that we cannot perform fake call of energy itself. The next interface serves a technique of mocking protected methods in Java:

package com.intelrate.mockmethod.impl;

public interface MockInterface {
Object mockMethod(Object parameter);

It's time to see how we can use it to test kineticEnergy calculation in JUnit + JMock:

package com.intelrate.mockmethod.impl;

import static org.junit.Assert.assertEquals;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

public class EinsteinFormulaImplTest {

private final Mockery context = new JUnit4Mockery();

private MockInterface mockInterface;

private final static double DELTA = 0.001;

public void setUp() {
mockInterface = context.mock(MockInterface.class);

public void testKineticEnergy() {
EinsteinFormulaImpl einsteinFormula = new EinsteinFormulaImpl() {
double energy(final double mass) {
return (Double) mockInterface.mockMethod(mass);

final double restMass = 10.0;
final double velocity = 100000000.0;
final double expectedEnergy = 5.4601175017849928E16;
final double mockRestEnergy = 8.987551787368178E17;

context.checking(new Expectations() { {
} });

assertEquals(expectedEnergy, einsteinFormula.kineticEnergy(
restMass, velocity), DELTA);

The idea behind this test is simple - we provide rest mass and velocity of some physical body and expect that its kinetic energy will be equal to predefined value. At the same time we use JMock to mock our helper interface which controls that energy method was called with mass parameter and returned mockRestEnergy to the tested method.

Summarizing this idea, we've got a clear code with optimal interface and really modular test at the same time.



Anonymous said...

Why not simply use powermock (http://code.google.com/p/powermock/)? It supports mocking of private/protected/final/static/etc.

powermock is probably the best testing tool I came across in 2008.

Pavel said...

It's interesting. Thanks.

Actually I would recommend to mock only behavior described in interfaces. When I apply such workaround for protected methods I understand why it is done. Libraries like CGLIB or powermock are powerful but very dangerous.

I hope you see what I mean here :)