Repository: mockito/mockito
Issue: mockito-android "Could not look up implicit location for storing generated classes" with Jetpack (androidx) 
Labels: android

I have Android emulator tests with these basic dependencies: 
```
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
androidTestImplementation 'androidx.test:rules:1.1.0-alpha4'
androidTestImplementation 'org.mockito:mockito-android:2.21.0'
```
Attempting to mock any interface results in exceptions similar to the following:

```
org.mockito.exceptions.base.MockitoException:
Mockito cannot mock this class: interface com.bumptech.glide.request.RequestListener.

Mockito can only mock non-private & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.



IMPORTANT INFORMATION FOR ANDROID USERS:

The regular Byte Buddy mock makers cannot generate code on an Android VM!
To resolve this, please use the 'mockito-android' dependency for your application:
http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22mockito-android%22%20g%3A%22org.mockito%22

Java               : 0.9
JVM vendor name    : The Android Project
JVM vendor version : 2.1.0
JVM name           : Dalvik
JVM version        : 0.9
JVM info           : null
OS name            : Linux
OS version         : 3.18.91+


Underlying exception : org.mockito.exceptions.base.MockitoException:
Could not look up implicit location for storing generated classes

You can configure an explicit location by setting the system property
'org.mockito.android.target' to a folder for storing generated class files
This location must be in private scope for most API versions, for example:

MyActivity.this.getDir("target", Context.MODE_PRIVATE)
or
getInstrumentation().getTargetContext().getCacheDir().getPath()
```

A complete project where this is reproducible is available here: https://github.com/sjudd/glide/tree/broken_androidx_mockito_android

After checking out the project (and branch) and starting an Android emulator, you can reproduce with `./gradlew :instrumentation:connectedCheck.`

I believe this is caused by Mockito relying on reflection with the android.support package here: https://github.com/mockito/mockito/blob/ee175c682aca82ac25fd2d00250f5188d6a9e954/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidTempFileLocator.java#L26-L30

A simple solution is to just add in a check for the identical class in the androidx package. I'll send a pull request for that shortly.




Issue comments:
I suppose it's worth noting that in the (hopefully) very short term, adding this class in the appropriate package is a simple workaround if you don't want to generalize setting the suggested property:

```java
package android.support.test;

import android.content.Context;

public class InstrumentationRegistry {
  public static Context getTargetContext() {
    return androidx.test.InstrumentationRegistry.getTargetContext();
  }
}
```
I did this in the class where I got this error and it fixed the problem for me. 

`static {
        System.setProperty("org.mockito.android.target", ApplicationProvider.getApplicationContext().getCacheDir().getPath());    
}`
This should be fixed in #1583

Pull request review comments:
Can you refactor the common part into a method so that only the String is different? That makes maintaining this piece of code a bit easier.
done

Patch that resolved the issue:
diff --git a/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidTempFileLocator.java b/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidTempFileLocator.java
index a79816c4f5..34e179b40f 100644
--- a/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidTempFileLocator.java
+++ b/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidTempFileLocator.java
@@ -23,12 +23,10 @@ class AndroidTempFileLocator {
         } catch (Throwable ignored) {
         }
         if (t == null) {
-            try {
-                Class<?> clazz = Class.forName("android.support.test.InstrumentationRegistry");
-                Object context = clazz.getDeclaredMethod("getTargetContext").invoke(clazz);
-                t = (File) context.getClass().getMethod("getCacheDir").invoke(context);
-            } catch (Throwable ignored) {
-            }
+            t = getCacheDirFromInstrumentationRegistry("android.support.test.InstrumentationRegistry");
+        }
+        if (t == null) {
+            t = getCacheDirFromInstrumentationRegistry("androidx.test.InstrumentationRegistry");
         }
         if (t == null) {
             try {
@@ -46,6 +44,16 @@ class AndroidTempFileLocator {
         target = t;
     }
 
+    private static File getCacheDirFromInstrumentationRegistry(String className) {
+        try {
+            Class<?> clazz = Class.forName(className);
+            Object context = clazz.getDeclaredMethod("getTargetContext").invoke(clazz);
+            return (File) context.getClass().getMethod("getCacheDir").invoke(context);
+        } catch (Throwable ignored) {
+        }
+        return null;
+    }
+
     private static File[] guessPath(String input) {
         List<File> results = new ArrayList<File>();
         for (String potential : splitPathList(input)) {


Test patch: