11

enter image description hereFinal classes can be mocked under java/test when I define in gradle:

testCompile "org.mockito:mockito-inline:+"

How to mock final classes under java/androidTest? This solution does not work:

androidTestCompile "org.mockito:mockito-android:+"

Do you have any ideas?

user1685503
  • 173
  • 1
  • 10
  • It is not a duplication. I want to know if it is possible to do it for Android Platform. – user1685503 Aug 23 '17 at 15:21
  • Mockito behaviour should be identical between `test/` and `androidTest/`, the fact that you're running the tests on an Android device rather than a JVM should make no difference as it's not part of the Android framework. – Michael Dodd Aug 23 '17 at 15:24
  • Mockito 2 {testCompile "org.mockito:mockito-core:+" and androidTestCompile "org.mockito:mockito-android:+" } does not introduce mocking final classes. To do that instead of org.mockito:mockito-core I need to use org.mockito:mockito-inline:+. And it works fine for test/ but it does not for androidTest/. I am wondering what change do I need to do in order to enable it under androidTest package. – user1685503 Aug 23 '17 at 15:28
  • Use inline with connected tests by adding `androidTestCompile "org.mockito:mockito-inline:+"`? – Michael Dodd Aug 23 '17 at 15:30
  • When I do that I receive an exception that for androidTestCompile I should use org.mockito:mockito-android:+. I found also a hint to add a file: java/com/(androidTest)resources/mockito-extensions/org.mockito.plugins.MockMaker containing the value mock-maker-inline. But it does not work either. – user1685503 Aug 23 '17 at 15:32

4 Answers4

8

Mocking final classes is not supported for mockito-android as per this GitHub issue.

From one of the library maintainers:

There is no real possibility to make [mocking 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.

There are some options to replace it depending on your use case.

Option 1: Use wrappers

If you wish to mock a final Android system class like BluetoothDevice you can simply create a non-final wrapper around that class and consume the BluetoothDeviceWrapper in your code instead of the BluetoothDevice:

class BluetoothDeviceWrapper {

   private final BluetoothDevice bluetoothDevice;

   BluetoothDeviceWrapper(BluetoothDevice bluetoothDevice) {
       this.bluetoothDevice = bluetoothDevice;
   }

   public String getName() {
       return bluetoothDevice.getName();
   }
}

Pro tip: you can use Android Studio's Generate / Delegate methods to generate delegate methods like getName() for you by pressing Alt-Ins or Cmd-N and choosing the correct option. See this answer for a more detailed example.

Option 2: use a testing framework like Robolectric

Robolectric provides working test doubles (called shadows) of Android classes like Context and SQLiteDatabase. You may be able to find a shadow of the class you are trying to mock in your test out of the box.

Option 3: use DexOpener

You can also try the library DexOpener with the ability to mock final classes in Android.

David Rawson
  • 20,912
  • 7
  • 88
  • 124
4

You may now use dexmaker-mockito-inline. See here for details regarding variants of Mockito and their capabilities.

Julian A.
  • 10,928
  • 16
  • 67
  • 107
0

I just got a response that the final mock maker does not work on Android.

https://github.com/mockito/mockito/issues/1173#issuecomment-324401986

user1685503
  • 173
  • 1
  • 10
0

final classes, objects, constructors can all be mocked with mockk https://mockk.io/

hmac
  • 267
  • 3
  • 9