Over a million developers have joined DZone.

Mock Final Class

· DevOps Zone

The DevOps zone is brought to you in partnership with Sonatype Nexus. The Nexus suite helps scale your DevOps delivery with continuous component intelligence integrated into development tools, including Eclipse, IntelliJ, Jenkins, Bamboo, SonarQube and more. Schedule a demo today

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 known 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 projects 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 class

Refactoring considerations

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

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 class by PowerMock framework. Example covers:

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

Final class:

public final class Plane {
	public static final int ENGINE_ID_RIGHT = 2;
	public static final int ENGINE_ID_LEFT = 1;

	public boolean verifyAllSystems() {
		throw new UnsupportedOperationException("Fail if not mocked!");
	}

	public void startEngine(int engineId) {
		throw new UnsupportedOperationException(
				"Fail if not mocked! [engineId=" + engineId + "]");
	}
}

Class under test:

public class Pilot {
	private Plane plane;

	public Pilot(Plane plane) {
		this.plane = plane;
	}

	public boolean readyForFlight() {
		plane.startEngine(Plane.ENGINE_ID_LEFT);
		plane.startEngine(Plane.ENGINE_ID_RIGHT);
		return plane.verifyAllSystems();
	}
}

Test:

@PrepareForTest(Plane.class)
public class PilotTest extends PowerMockTestCase {
	@Test
	public void testReadyForFlight() {
		Plane planeMock = PowerMockito.mock(Plane.class);
		Pilot pilot = new Pilot(planeMock);

		Mockito.when(planeMock.verifyAllSystems()).thenReturn(true);

		// testing method
		boolean actualStatus = pilot.readyForFlight();

		Assert.assertEquals(actualStatus, true);
		Mockito.verify(planeMock).startEngine(Plane.ENGINE_ID_LEFT);
		Mockito.verify(planeMock).startEngine(Plane.ENGINE_ID_RIGHT);
	}
}

Links

Source code can be downloaded from Github.

Other unusual mocking examples:

The DevOps zone is brought to you in partnership with Sonatype Nexus. Use the Nexus Suite to automate your software supply chain and ensure you're using the highest quality open source components at every step of the development lifecycle. Get Nexus today

Topics:

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}