8

Hi i am trying to mock a final class(as all classes in kotlin are final by default) and added the following dependencies in my gradle:

testImplementation 'junit:junit:4.12'
testImplementation 'au.com.dius:pact-jvm-consumer-junit_2.11:3.5.10'
testImplementation "org.mockito:mockito-android:2.13.0"
testImplementation 'org.mockito:mockito-inline:2.13.0'
testImplementation "org.mockito:mockito-core:2.13.0"
//testImplementation 'io.mockk:mockk:1.8'
testImplementation 'org.assertj:assertj-core:3.8.0'

androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
androidTestImplementation 'junit:junit:4.12'
androidTestImplementation "org.mockito:mockito-core:2.13.0"
androidTestImplementation "org.mockito:mockito-android:2.13.0"
androidTestImplementation 'org.mockito:mockito-inline:2.13.0'
androidTestImplementation "com.android.support.test.espresso:espresso-intents:3.0.2"

the mockito-inline is supposed to enable you to mock a final kotlin class and so i added to both my java unit test and my instrumental test using testImplementation and androidTestImplementation

On building the project i get the following error:

More than one file was found with OS independent path 'mockito-extensions/org.mockito.plugins.MockMaker'

Any ideas whats going on? if i remove the androidTestImplementation of the mockitio inline, it compiles fine but when running intrumental test i get the mockito error saying it cannot mock a final class.

tynn
  • 38,113
  • 8
  • 108
  • 143
Jono
  • 17,341
  • 48
  • 135
  • 217

4 Answers4

6

In order to be able to mock final classes in Kotlin, you’ll need to create a file org.mockito.plugins.MockMaker (literally) that contains only this line

mock-maker-inline

and place it into test/resources/mockito-extensions.

For more info please read https://antonioleiva.com/mockito-2-kotlin/.

Demigod
  • 5,073
  • 3
  • 31
  • 49
  • 4
    I don't think this is true anymore. That's the point of the inline dependency. Also, I'm pretty sure we can't (yet) mock final classes in the androidTest source set. Some limitation of the Android SDK. – AutonomousApps May 21 '18 at 22:28
  • Works fine for me. Have you tried to run just unit test with this file? Could it be as stated here - https://stackoverflow.com/a/40992880/3569545 – Demigod May 22 '18 at 09:00
  • Every thing fine with the approach. I'm using it in my unit tests. What are you trying to mock? Message "More than one file was found with OS independent path 'mockito-extensions/org.mockito.plugins.MockMaker'" could say that several libs are placing such file, do you need all those imports in build.gradle? – Demigod May 22 '18 at 13:46
  • putting this file in the androidTest resources dir cleared this issue for me - i didn't need this until after I migrated to androidx and had to update many libraries like mockito – bsautner Jul 25 '19 at 17:26
3

mockito-inline won't work for instrumentation tests. In order to be able to mock final classes in instrumentation tests you just need to include the following line only:

androidTestImplementation com.linkedin.dexmaker:dexmaker-mockito-inline:2.28.0

Refer to its Github page for more details

This thread might also be useful.

Nijat Ahmadli
  • 711
  • 6
  • 13
1

As per this answer you cannot mock final classes in androidTest- it is a limitation explained in the Mockito Github issue tracker here:

There is no real possibility to make this [mocking of final classes] work in Android at the moment as it lacks the instrumentation API on top of which we are operating. The Android VM is not a standard VM and only implements a subset of the Java specification. As long as Google does not choose to extend its JVM, I am afraid that this feature will not work.

David Rawson
  • 20,912
  • 7
  • 88
  • 124
  • So i would need to just make the class Open? – Jono May 22 '18 at 08:52
  • @jonney can you depend on interfaces rather than concrete final classes? – David Rawson May 22 '18 at 08:55
  • You're talking about mocking final classes in Java. But the question touches Kotlin. In Kotlin it is possible. You don't have to add `open` keyword to every class you want to mock. – Demigod May 22 '18 at 09:09
  • You do though, how else can you make the class none final? Na i need to use proper impl of the class, i do have interfaces but i test the actual Impl using a spy and just mock the underlining data but still have my impl perform real world logic to a mocked data – Jono May 22 '18 at 11:21
0

In my case, I got this error because I use implementation "org.mockito:mockito-inline:2.13.0" instead of testImplementation "org.mockito:mockito-inline:2.13.0"

Kharda
  • 1,318
  • 14
  • 23