Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot mock final Kotlin class using Mockito 2

Tags:

I am unable to mock a Kotlin final class using Mockito 2. I am using Robolectric in addition.

This is my test code:

@RunWith(RobolectricTestRunner.class) @Config(constants = BuildConfig.class, sdk = 21) public class Test {      // more mocks      @Mock     MyKotlinLoader kotlinLoader;      @Before     public void setUp() {         MockitoAnnotations.initMocks(this);     } } 

The test fails when we try to initialise the mocks in the setUp() method.

In addition, I am using the following gradle dependencies in my code:

testCompile 'org.robolectric:robolectric:3.3.2' testCompile 'org.robolectric:shadows-multidex:3.3.2' testCompile 'org.robolectric:shadows-support-v4:3.3.2' testCompile("org.powermock:powermock-api-mockito2:1.7.0") {     exclude module: 'hamcrest-core'     exclude module: 'objenesis' } testCompile 'junit:junit:4.12' testCompile 'org.mockito:mockito-inline:2.8.9' 

All other unit tests pass using this configuration but as soon as I try to mock the Kotlin class it throws the following error:

Mockito cannot mock/spy because : - final class

Please note I am using Mockito version 2 and I am using the inline dependency which automatically enables the ability to mock final classes.

like image 693
blackpanther Avatar asked Jul 17 '17 11:07

blackpanther


People also ask

Can we mock final class using Mockito?

You cannot mock a final class with Mockito, as you can't do it by yourself.

Does Mockito work with Kotlin?

Mockito has been around since the early days of Android development and eventually became the de-facto mocking library for writing unit tests. Mockito and Mockk are written in Java and Kotlin, respectively, and since Kotlin and Java are interoperable, they can exist within the same project.

What is a final class Kotlin?

final: defaultThe final modifier mark classes and methods as not allowed to be overridden. In Kotlin this is the default. This decision was made to avoid fragile base class problem. It happens when a small change in base classes (super classes) make subclasses to malfunction.


2 Answers

PowerMock implements its own MockMaker which leads to incompatibility with Mockito mock-maker-inline, even if PowerMock is just added as a dependency and not used. If two org.mockito.plugins.MockMaker exist in path then any only one can be used, which one is undetermined.

PowerMock can however delegate calls to another MockMaker, and for then tests are run without PowerMock. Since PowerMock 1.7.0 this can be configured with using the PowerMock Configuration.

The MockMaker can be configured by creating the file org/powermock/extensions/configuration.properties and setting:

mockito.mock-maker-class=mock-maker-inline 

Example of using Mockito mock-maker-inline with PowerMock: https://github.com/powermock/powermock-examples-maven/tree/master/mockito2

like image 93
Arthur Zagretdinov Avatar answered Oct 01 '22 15:10

Arthur Zagretdinov


Since Mockito 2.1.0 there is a possibility to mock final types, enums, and final methods. It was already mentioned in the comments to the original question.

To do this, you’ll need to create a folder (if dont exist) test/resources/mockito-extensions and add there file with the name org.mockito.plugins.MockMaker and this line:

mock-maker-inline 

enter image description here

Links to documentation and tutorial

like image 41
Roman Nazarevych Avatar answered Oct 01 '22 15:10

Roman Nazarevych