Mock final method

Foreword

If you already read some other blog post about unusual mocking, you can skip prelude via this link.

I was asked to put together examples how to mock Java constructs well know for their testability issues:

I am calling these techniques unusual mocking. I was worried that such examples without any guidance can be widely used by teammates not deeply experienced in mocking frameworks.

Developers practicing TDD or BDD should be aware of testability problems behind these constructs and try to avoid them when designing their tests and modules. That is the reason why you probably wouldn’t be facing such unusual mocking often on project using these great programming methodologies.

But sometimes you have to extend or maintain legacy codebase that usually contains low cohesive classes. In most cases there isn’t time in current hectic agile world to make such class easy to unit test standard way. When you are trying to unit test such class you often realize that unusual mocking is needed.

That is why I decided to create and share refactoring considerations alongside with examples and workarounds for unusual mocking. Examples are using Mockito and PowerMock mocking frameworks and TestNG unit testing framework.

Mock final method

Refactoring considerations

Change method to non-final (remove final keyword) and test it standard way. This is technique I use always when I can change code of final method.

Usage of PowerMock

Before usage of this example, please carefully consider if it is worth to bring bytecode  manipulation risks into your project. They are gathered in this blog post. In my opinion it should be used only in very rare and non-avoidable cases.

Test shows how to mock final method by PowerMock framework. Example covers:

  1. Mocking of final method with return value
  2. Mocking of final void method
  3. Verifying of final method calls

Class with final methods:

public class Bike {
	public final void shiftGear(boolean easier) {
		throw new UnsupportedOperationException("Fail if not mocked! [easier="
				+ easier + "]");
	}

	public final int getGear() {
		throw new UnsupportedOperationException("Fail if not mocked!");
	}
}

Class under test:

public class Rider {
	private Bike bike;

	public Rider(Bike bike) {
		this.bike = bike;
	}

	public int prepareForUphill() {
		int gear = bike.getGear();
		for (int idx = 0; idx < 2; idx++) {
			bike.shiftGear(true);
			gear++;
		}
		return gear;
	}
}

Test:

@PrepareForTest(Bike.class)
public class RiderTest extends PowerMockTestCase {
	private static final int TESTING_INITIAL_GEAR = 2;

	@Test
	public void testShiftGear() {
		Bike mock = PowerMockito.mock(Bike.class);

		Rider rider = new Rider(mock);
		Mockito.when(mock.getGear()).thenReturn(TESTING_INITIAL_GEAR);

		// invoke testing method
		int actualGear = rider.prepareForUphill();

		Assert.assertEquals(actualGear, TESTING_INITIAL_GEAR + 2);
		Mockito.verify(mock, Mockito.times(2)).shiftGear(true);
	}
}

Links

Source code can be downloaded from Github.

Other unusual mocking examples:

3 thoughts on “Mock final method

  1. hi,Lubos Krnac:
    When I user powermock-mockito to do test,I want to test a final method in abstract class,like this:
    public abstract class AbstractClass {
    public final String finalMethod() {
    return “finalMethod…”;
    }
    }
    how can I mock finalMethod(),sorry about my english,anything will be helpful,thx.

  2. I guess you can create test implementation of your abstract class, e.g.:

    public class ClassUsedForTesting extends AbstractClass {
    }

    and test is the way as described in the blog post.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.