Mockito
Final Class
Unit Testing
Java Programming
Software Development

How to mock a final class with mockito

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

When testing Java applications, one often encounters scenarios where interaction with external dependencies might need to be simulated. In many cases, this means mocking classes to ensure tests are fast and dependable. Mockito is one of the most popular frameworks used for this purpose, due to its straightforward and readable syntax and extensive features. However, mocking final classes and methods with Mockito requires a bit of special handling.

Understanding final in Java

In Java, the final keyword can be applied to classes, methods, and variables. When a class is marked as final, it cannot be subclassed. This presents a particular situation in unit testing because mocking frameworks like Mockito traditionally work by creating a subclass of the class to be mocked.

Initial Challenges with Mockito

Earlier versions of Mockito (before 2.x) did not allow mocking of final classes and methods directly. This limitation required developers to use workarounds or opt for other tools when faced with final systems. However, with the introduction of Mockito 2, capabilities for mocking final classes and methods were integrated, albeit they need to be explicitly enabled.

Enabling Mocking of Final Classes and Methods

To start mocking final classes and methods with Mockito 2.x and later, you need to add some configuration. The setup involves creating a file named org.mockito.plugins.MockMaker and placing it in the resources/mockito-extensions directory of your application. The file should contain one line:

 
mock-maker-inline

This configuration essentially switches Mockito to an alternative mechanism (inline-mocking) that doesn't rely on subclassing but rather instruments the classes directly.

Mocking a Final Class: An Example

Consider a scenario where you have a final class that you want to mock in your unit testing:

java
1public final class PaymentProcessor {
2
3    public boolean processPayment(BigDecimal amount) {
4        // Implementation here
5        return true;
6    }
7}

To write a test for a class that integrates with PaymentProcessor, you would do something like:

java
1import static org.mockito.Mockito.*;
2import org.junit.jupiter.api.Test;
3import java.math.BigDecimal;
4
5public class PaymentServiceTest {
6
7    @Test
8    public void testPaymentProcessing() {
9        // Create a mock instance of PaymentProcessor
10        PaymentProcessor mockProcessor = mock(PaymentProcessor.class);
11
12        // Define behavior of mock
13        when(mockProcessor.processPayment(any(BigDecimal.class))).thenReturn(true);
14
15        // Testing code that uses the mock
16        PaymentService paymentService = new PaymentService(mockProcessor);
17        boolean result = paymentService.makePayment(new BigDecimal("100.00"));
18
19        // Assertion
20        assertTrue(result);
21    }
22}

In this example, PaymentProcessor is a final class. The test uses Mockito to mock it and stipulates the desired behavior, which is then used in a test assertion.

Considerations and Best Practices

While mocking final classes is supported, it’s essential to use this capability judiciously:

  • Design Implications: The need to mock final classes might indicate design decisions that could be reevaluated. Consider whether high coupling and limited flexibility in the design necessitate the use of final classes.
  • Testing Philosophy: Mocking should not replace good design practices. Dependence on extensive mocking might also signify the need for refactoring to simpler, more testable designs.
  • Performance: Be mindful that the use of inline-mocking can affect the performance of your tests. In scenarios with extensive mocking requirements, this might become noticeable.

Summary Table

FeatureRequirement / ActionPurpose
Mocking final classes or methodsEnable inline-mockingAllows Mockito to mock classes and methods declared as final.
Mocking regular classesStandard Mockito setupUsed for classes and methods not declared as final.
Performance considerationsEvaluate impactInline-mocking can slow down test execution times.
Testing philosophyReflect on necessityExtensive mocking might indicate need for design improvements.

In conclusion, Mockito’s capability to mock final classes is a valuable tool in the arsenal of a modern Java developer, yet it comes with considerations that should be carefully evaluated within the context of your project’s testing and design practices.


Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.