Java mockito mock final class

Mocking final method with Mockito framework

In this article, we will show a way to mock the final method with Mockito testing framework. Fortunately, from version 2 Mockito supports final classes and methods.

2. Mocking final method using mockito-inline

The following dependency need to be added into your project in order to start mocking final/static methods in unit tests:

 org.mockito mockito-inline 3.6.28 test  

The latest version of this library could be found here.

When you try to mock final/static classes with an older version of Mockito or without configuring mockito-inline dependency you will face the error like this:

Mockito cannot mock/spy because : - final class 

The best way to explain how mocking final methods works is to present a simple piece of code with an example.

Let’s consider we have a final class with a final method that returns a welcome message:

package com.frontbackend.libraries.mockito; public final class FinalWelcomeUtil < public final String getWelcomeMessage(String name) < return String.format("Welcome %s", name); >> 

The unit test that makes use of Mockito to mock this final class could have the following structure:

package com.frontbackend.libraries.mockito; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; import org.junit.Test; public class MockitoFinalMethodTest < @Test public void testMockingFinalMethod() < FinalWelcomeUtil finalClass = new FinalWelcomeUtil(); FinalWelcomeUtil mock = mock(FinalWelcomeUtil.class); given(mock.getWelcomeMessage("John")).willReturn("not anymore"); assertNotEquals(mock.getWelcomeMessage("John"), finalClass.getWelcomeMessage("John")); assertEquals("not anymore", mock.getWelcomeMessage("John")); assertEquals("Welcome John", finalClass.getWelcomeMessage("John")); >> 

In this code first, we initialize FinalWelcomeUtil to check if the ‘untouched’ class will behavior as implemented. Then we create a mock and configure the final getWelcomeMessage method to return always static text regardless of input parameters.

The following assertions confirm that mocking final method works:

assertEquals("not anymore", mock.getWelcomeMessage("John")); assertEquals("Welcome John", finalClass.getWelcomeMessage("John")); 

3. Conclusion

This article presented an easy way to mock the final method with the Mockito framework. Note that mocking this kind of method is not recommended and need to be explicitly activated to be available.

As usual the code used as an example in this article is available under our GitHub repository.

Источник

How to mock a final class with mockito in Java?

Mocking is an important technique in software testing, as it enables developers to test the behavior of isolated parts of a system. However, it can sometimes be challenging to mock final classes, which are classes that have been marked as final and cannot be extended. Final classes are typically used in Java to ensure that a class’s implementation cannot be changed, making them a good choice for critical system components. However, this can make it difficult to test these classes effectively.

Читайте также:  Php command in terminal

Method 1: PowerMock

Mocking a final class with PowerMock

Mocking a final class with Mockito is not possible. However, we can use PowerMock to mock a final class in Java. Here are the steps to do so:

Step 1: Add PowerMock dependencies

To use PowerMock, we need to add the following dependencies to our project:

dependency> groupId>org.powermockgroupId> artifactId>powermock-coreartifactId> version>2.0.9version> scope>testscope> dependency> dependency> groupId>org.powermockgroupId> artifactId>powermock-module-junit4artifactId> version>2.0.9version> scope>testscope> dependency>

Step 2: Enable PowerMockito

To enable PowerMockito, we need to add the following annotations to our test class:

@RunWith(PowerMockRunner.class) @PrepareForTest(FinalClass.class) public class FinalClassTest  // . >

The @RunWith(PowerMockRunner.class) annotation tells JUnit to use the PowerMock runner, and the @PrepareForTest(FinalClass.class) annotation tells PowerMock to prepare the FinalClass for mocking.

Step 3: Mock the final class

To mock the final class, we can use the PowerMockito.mock() method:

FinalClass mockedFinalClass = PowerMockito.mock(FinalClass.class);

Step 4: Define the behavior of the mocked class

We can define the behavior of the mocked class using the when() method:

PowerMockito.when(mockedFinalClass.someMethod()).thenReturn("mocked result");

Step 5: Use the mocked class

We can now use the mocked class in our test:

assertEquals("mocked result", mockedFinalClass.someMethod());

Full example

@RunWith(PowerMockRunner.class) @PrepareForTest(FinalClass.class) public class FinalClassTest  @Test public void testFinalClass()  FinalClass mockedFinalClass = PowerMockito.mock(FinalClass.class); PowerMockito.when(mockedFinalClass.someMethod()).thenReturn("mocked result"); assertEquals("mocked result", mockedFinalClass.someMethod()); > >

In this example, we have mocked the FinalClass and defined the behavior of the someMethod() method to return «mocked result». We have then used the mocked class in our test and asserted that the result is «mocked result».

Method 2: Using Reflection

Mocking final classes in Java can be a tricky task, as Mockito does not support mocking final classes out of the box. However, there is a way to achieve this using reflection. In this tutorial, we will go through the steps required to mock a final class using Mockito and reflection.

Step 1: Create a Final Class to be Mocked

First, we need to create a final class that we want to mock. For the purpose of this tutorial, we will create a simple final class called FinalClass with a single method called finalMethod() .

public final class FinalClass  public String finalMethod()  return "Hello World!"; > >

Step 2: Create a Test Class

Next, we need to create a test class that will mock the final class using reflection. In this example, we will create a test class called FinalClassTest .

import org.junit.Test; import org.mockito.Mockito; public class FinalClassTest  @Test public void testFinalClass() throws Exception  FinalClass finalClassMock = Mockito.mock(FinalClass.class); Mockito.when(finalClassMock.finalMethod()).thenReturn("Mocked Hello World!"); System.out.println(finalClassMock.finalMethod()); > >

Step 3: Create a Mocked Final Class Using Reflection

In the testFinalClass() method, we create a mock of the final class using Mockito’s mock() method. However, since the class is final, Mockito will not be able to create a mock of it. Therefore, we need to create a mocked final class using reflection.

import org.junit.Test; import org.mockito.Mockito; import java.lang.reflect.Field; import java.lang.reflect.Modifier; public class FinalClassTest  @Test public void testFinalClass() throws Exception  FinalClass finalClassMock = Mockito.mock(FinalClass.class); Field field = FinalClass.class.getDeclaredField("INSTANCE"); field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); field.set(null, finalClassMock); Mockito.when(finalClassMock.finalMethod()).thenReturn("Mocked Hello World!"); System.out.println(finalClassMock.finalMethod()); > >

In the testFinalClass() method, we first create a mock of the final class using Mockito’s mock() method. Then, we use reflection to access the private static field of the final class called INSTANCE . We set this field to the mock object we created earlier.

However, since the INSTANCE field is final, we need to remove the final modifier using reflection. We do this by accessing the modifiers field of the Field class and setting it to the bitwise AND of the current modifiers and the bitwise complement of the final modifier.

Finally, we use Mockito’s when() method to specify the behavior of the finalMethod() method when called on the mock object. In this example, we simply return the string «Mocked Hello World!».

Step 4: Run the Test

Now, we can run the test and see the output.

As we can see, the test has successfully mocked the final class using reflection.

Method 3: Using bytecode manipulation with ByteBuddy

Mockito is a popular Java mocking framework that allows developers to create mock objects for testing purposes. However, Mockito cannot mock final classes, as Java does not allow subclasses of final classes. One solution to this problem is to use bytecode manipulation with ByteBuddy.

Here are the steps to mock a final class with Mockito using ByteBuddy:

dependency> groupId>net.bytebuddygroupId> artifactId>byte-buddyartifactId> version>1.10.22version> dependency> dependency> groupId>org.mockitogroupId> artifactId>mockito-coreartifactId> version>3.11.2version> scope>testscope> dependency>
  1. Create a custom implementation of the Mockito MockMaker interface that uses ByteBuddy to create the mock object:
import net.bytebuddy.ByteBuddy; import net.bytebuddy.implementation.MethodDelegation; import net.bytebuddy.matcher.ElementMatchers; import org.mockito.MockSettings; import org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker; public class ByteBuddyMockMakerImpl extends ByteBuddyMockMaker  @Override protected T> T createMock(MockCreationSettingsT> settings, MockHandler handler)  if (settings.getTypeToMock().isInterface() || Modifier.isAbstract(settings.getTypeToMock().getModifiers()))  return super.createMock(settings, handler); > return new ByteBuddy() .subclass(settings.getTypeToMock()) .method(ElementMatchers.isDeclaredBy(settings.getTypeToMock())) .intercept(MethodDelegation.to(handler, "handle")) .make() .load(settings.getTypeToMock().getClassLoader()) .getLoaded() .newInstance(); > >
import org.mockito.Mockito; public class MyTest  @BeforeClass public static void setup()  Mockito.framework().setMockMaker(new ByteBuddyMockMakerImpl()); > @Test public void testMockFinalClass()  final FinalClass mock = Mockito.mock(FinalClass.class); Mockito.when(mock.someMethod()).thenReturn("Hello, World!"); assertEquals("Hello, World!", mock.someMethod()); > >

In the example above, we create a mock object for the final class FinalClass using Mockito. We then use Mockito to set an expectation for the behavior of the someMethod() method of the mock object. Finally, we assert that the method returns the expected value.

By following these steps, you can use Mockito to mock final classes in your Java projects using ByteBuddy.

Источник

Mock final class and final method with Mockito

This post explains how to mock final methods and classes. Mockito doesn’t support this behavior by default. To stub final methods and mock final classes, we need to enable the inline mock maker first. When you try to mock a final class without the mockito inline mockmaker you get an error message like this: mockito cannot mock/spy because : — final class .

Maven Dependency

For the examples, I used version 4.2.0 of Mockito.

We also need the inline mock maker to stub final classes/methods. We can add a dependency or create a file inside the test resources to enable the new Mock maker.

Option 1: Inline mock maker dependency

Add this dependency in your pom.

Option 2: Adding a file to enable the inline mock maker

Create a resources directory in your test directory if you do not have one already. Inside the resources create the directory mockito-extensions and in that directory the file org.mockito.plugins.MockMaker . The complete path with file should look like this: src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker .

In the file org.mockito.plugins.MockMaker paste this text mock-maker-inline , now the mock maker is available during tests.

Mocking final class and methods

With inline mock maker, mocking a final class or method is the same as mocking a non-final class or method. Below we have an example that mocks the final class Cat . You can’t tell from the @Test annotated method that we mock a final class.

Mocking final methods also doesn’t look any different from mocking a non-final method.

Conclusion

In this post, we enabled the inline mock maker to mock final methods and classes. We also saw two examples of how to mock a final class and method and that it looks the same as mocking non-final classes and methods.

If you’re curious and want to know more about what you can do with Mockito, please check out their documentation: https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html. It lists all the Mockito features and how to use them.

Further reading

More about testing in Java:

Источник

Оцените статью