Final Method Mocking

Final method mocking

There is no support for mocking final methods in Mockito.

As Jon Skeet commented you should be looking for a way to avoid the dependency on the final method. That said, there are some ways out through bytecode manipulation (e.g. with PowerMock)

A comparison between Mockito and PowerMock will explain things in detail.

How to mock a final class with mockito

Mocking final/static classes/methods is possible with Mockito v2 only.

add this in your gradle file:

testImplementation 'org.mockito:mockito-inline:2.13.0'

This is not possible with Mockito v1, from the Mockito FAQ:

What are the limitations of Mockito

  • Needs java 1.5+

  • Cannot mock final classes


...

Nullpointer Exception for mocking final method

The NullPointerException comes from the invocation of the getAsMap method.

Using Mockito.doReturn(map).when(aggs).getAsMap(); instead should solve that issue.

However there seems to be a bug in PowerMockito as writing it like this is not supposed to trigger the invocation of the getAsMap() method (which still happens).

I suggest you create a bug ticket in their bugtracker for this issue.


If you enable final mocking for Mockito (see here) running the test is successful.

@RunWith(MockitoJUnitRunner.class)
public class TestExample {

@Test
public void testMyMethod() {
Aggregations aggs = Mockito.mock(Aggregations.class);
Cardinality cardinality = Mockito.mock(Cardinality.class);
Map<String, Aggregation> map = new HashMap<String, Aggregation>();
map.put("sample", cardinality);

Mockito.doReturn(map).when(aggs).getAsMap();
Assert.assertEquals(map, aggs.getAsMap());
}
}

Another option might be to work with a real Aggregations object instead:

@Test
public void testMyMethod() {

Cardinality cardinality = Mockito.mock(Cardinality.class);
Mockito.when(cardinality.getName()).thenReturn("sample");

List<Aggregation> list = new ArrayList<>();
list.add(cardinality);

Aggregations aggs = new Aggregations(list);
Map<String, Aggregation> map = aggs.getAsMap();

Assert.assertEquals(1, map.size());
Assert.assertEquals(cardinality, map.get("sample"));
}

Mock an inherited final method

From Mockito's FAQ:

What are the limitations of Mockito?

[...]

  • Cannot mock final methods - their real behavior is executed without any exception. Mockito cannot warn you about mocking final methods so be vigilant.

[...]

For this, you need an extension like PowerMock. See this question for a working example. A throughout description can be found in PowerMock's documentation

Mock a method that's inside a final class using Mockito

Try to write a testable code. Example in your case, Your class is final and cannot be mocked, then your class can implement an interface, then you can absolutely mock the methods of the interface.

Your class is final and cannot be mocked

Why? Because a final class cannot be extended. By mocking a class/interface, the technique behind is it creates a subclass extends/implements the class/interface. Then if your class prevents extending by having final, you cannot mock it.

Note: you can use some power libs to mock final class (e.g. - powermockito), but I would not recommend this.



Related Topics



Leave a reply



Submit