I am trying to use Mockito in my Android project. I have found very nice tutorial that deals with it: http://www.paulbutcher.com/2012/05/mockito-on-android-step-by-step/
Basically it uses new version of Mockito + Dexmaker and everything works as expected.
However, when I try to mock some Android specific object i.e:
Context context = mock(Context.class);
I receive this exception:
java.lang.IllegalArgumentException:
dexcache == null (and no default could be found;
consider setting the 'dexmaker.dexcache' system property)
at com.google.dexmaker.DexMaker.generateAndLoad(DexMaker.java:359)
at com.google.dexmaker.stock.ProxyBuilder.buildProxyClass(ProxyBuilder.java:252)
at com.google.dexmaker.mockito.DexmakerMockMaker.createMock(DexmakerMockMaker.java:54)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26)
Any idea how to fix it?
From @rjath's comment of @MrChaz's answer, this works better for me:
System.setProperty(
"dexmaker.dexcache",
getInstrumentation().getTargetContext().getCacheDir().getPath());
I put it in my setUp()
method.
I've managed to piece together a fix that seems to be working for me.
To the manifest I added read and write external storage.
To the test I added System.setProperty("dexmaker.dexcache", "/sdcard");
to the test.
To the emulator image I added an SD card.
I believe this works because by default mockito tries to use the apps cache directory but I never run an activity so I suspect the directory is never created by the OS
So the problem is with Dexmaker not being able to find the cache path on Android >= 4.3 as other people mentioned and as described in this dexmaker issue.
I went with implementing the workaround in a custom instrumented test runner instead of in every test (or their superclass) setUp()
, because it feels a bit less hacky (it really is in only one place - and not inherited in every subclass) and more flexible.
For the sake of documentation these are the necessary changes to do this:
public class CustomInstrumentationTestRunner extends InstrumentationTestRunner {
@Override public void onCreate (final Bundle arguments) {
super.onCreate(arguments);
// temporary workaround for an incompatibility in current dexmaker (1.1) implementation and Android >= 4.3
// cf. https://code.google.com/p/dexmaker/issues/detail?id=2 for details
System.setProperty("dexmaker.dexcache", getTargetContext().getCacheDir().toString());
}
}
And set up your project (or test project) to use this class as the instrumented test runner in its AndroidManifest.xml
when building with ant:
<instrumentation
android:name="my.package.CustomInstrumentationTestRunner"
android:targetPackage="my.target.package" />
or its build.gradle
when building with gradle:
android {
defaultConfig {
// ...
testInstrumentationRunner 'my.package.CustomInstrumentationTestRunner'
}
// ...
}
If you have other instrumentation
entries, you can switch between them either on the command line or select one in your IDE running configuration.
I had this issue for an Android Library project but NOT for the application project! Setting the System property "dexmaker.dexcache" as mentioned above worked around the issue. I'm running Android 4.3 Nexus 4 device, building with 19.0.3 tools, target api 19, my dependencies:
androidTestCompile "org.mockito:mockito-core:1.9.5"
androidTestCompile "com.google.dexmaker:dexmaker:1.0"
androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.0"
It looks like the dexmaker project has moved from Google Code to GitHub.
In the maven central repository there are versions 1.1 and 1.2 published in March 2014 and December 2014.
I've verified this "dexcache == null" issue still exists through version 1.2 - but only on certain devices. For example, a Galaxy S5 with Android 5.0 has the problem, and a Galaxy S4 with Android 4.4.2 does not.
I cloned the GitHub repository (last commit March 12th 2015 - ca74669), and ran locally, and the problem has been fixed (there are also commits in the history that back this up). So once there is a 1.3 release, hopefully this problem is gone for good!
Anyone else wanting to run a local copy of 1.3-SNAPSHOT, here's how I did that (on a Mac, but other platforms should work too, you'll need mvn, adb, and dx on PATH):
git clone
https://github.com/crittercism/dexmaker.gitcd dexmaker
mvn install -Dmaven.test.skip=true
cp -R ~/.m2/repository/com/google/dexmaker $ANDROID_HOME/extras/android/m2repository/com/google
- Then change version in
app/build.gradle
:androidTestCompile 'com.google.dexmaker:dexmaker:1.3-SNAPSHOT'
- Or
pom.xml
if using maven to build, or overwrite yourlibs/dexmaker.jar
with~/.m2/repository/com/google/dexmaker/dexmaker/1.3-SNAPSHOT/dexmaker-1.3-SNAPSHOT.jar
if you are using eclipse/ant
- Or
Also, FYI, the original issue report for the same issue on Google Code as well.
You can add the mockito core as a dependency instead. Then, that error will not happen and you won't need a workaround.
dependencies {
...
testCompile 'org.mockito:mockito-core:1.10.19'
}
来源:https://stackoverflow.com/questions/12267572/mockito-dexmaker-on-android