Mockito + Dexmaker on Android - android

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 clonehttps://github.com/crittercism/dexmaker.git
cd 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 your libs/dexmaker.jar with ~/.m2/repository/com/google/dexmaker/dexmaker/1.3-SNAPSHOT/dexmaker-1.3-SNAPSHOT.jar if you are using eclipse/ant
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'
}

I observed this issue when did manipulations with resources and folders inside test folder. Actually just restarting Android Studio helped. Simple, but worked.

Related

Not able to view Dagger generated classes source code in IDE

I'm having trouble seeing the generated dagger classes in my project. The app builds, dagger injects the classes just fine, etc. but I can't actually view the dagger classes in my IDE - they show up as red (indicating an error), and trying to step into the class while debugging and/or viewing the source code to see how they are doing things doesn't work.
Here's a sample project that doesn't work for me: https://github.com/erikcaffrey/Dagger2-MVP-Sample
All I did was pull it, run it, and then went to the CategoryApplication class and tried to see the source for the DaggerAppComponent class, but I am not able to.
For reference, here's what I see:
Some additional information: On other computers I do not have this problem (Windows 10, MacBook Pro #2) but my main development MacBook Pro if affected by this. The dagger generated files exist in my project structure and I can view them manually - but ideally the IDE can pick these up and not show this as an error visually. I am using Android Studio 3.1.4 but this was also occurring in older versions (not sure on the exact numbers though)
The sample project I am using has the following gradle dependencies setup:
annotationProcessor 'com.google.dagger:dagger-compiler:2.15'
implementation 'com.google.dagger:dagger:2.15'
It doe snot use the android dagger components, nor the android support components, FWIW.
Update: I noticed that my Android Studio instance on my dev MacBook Pro does not list the dagger generated files in the app/build/generated/source/apt/ directory when viewing the project files in the 'Project' setting. The files on the hard drive do exist, but they do not show up in the IDE... so I doubt this is a dagger issue - just something wrong with the IDE not picking up these files.
def daggerVer = 2.12 // or latest version
implementation "com.google.dagger:dagger:$daggerVer"
implementation "com.google.dagger:dagger-android-support:$daggerVer"
annotationProcessor "com.google.dagger:dagger-android-processor:$daggerVer"
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVer"
In your build.gradle file, add this line:
dependencies {
apt 'com.google.dagger:dagger-compiler:2.0'
}
which will make the generated sources visible in android studio.
I noticed this was not an issue on Android Studio 3.2 beta, so I figured it was a configuration issue. I went ahead and uninstalled Android Studio and deleted all references to Android Studio from my machine and then reinstalled Android Studio 3.1.4. The issue is no longer occurring.

Build error with Android Studio 3.0 Canary 4

I am currently in the process of developing an Instant app, for which I have restructured my monolithic app into feature modules.
Everything was up and running till Android Studio canary 3, but after an update to Android Studio Canary 4 my project fails to build with the following error:
A problem was found with the configuration of task ':minimoBase:dataBindingExportBuildInfoDebugAndroidTest'.
> Directory '/Users/nayak.vishal/projectData/minimo_instant_app_project/putica-client-android-
native/minimoBase/build/intermediates/data-binding-info/androidTest/debug'
specified for property 'xmlOutFolder' does not exist.
The following procedure worked as a workaround for this issue:
Execute the following build commands on the gradle command line
1) gradlew clean
2) gradlew :appModule:assembleDebug
here appModule is the name of the app module for building the installable apk
the build is successful and the debug apk generated in the output folder can be installed successfully
3) gradlew :instantAppModule:assembleDebug
here instantAppModule is the name of the instant app module
the build is successful and the instant app apks can be installed and launched via deep link
Once the above command line builds are successful, building via Android Studio Canary 4 also stops throwing the build error.
I got similar error when I turn on data-binding for library module. When I turn it off and move all classes that require data-binding to app module, it works. So I guess there is a problem that DataBinding doesn't work on Library module any more ( Gradle 2.x fine with this).
dataBinding {
enabled = false
}
I am using com.android.tools.build:gradle:3.0.0-alpha5 and Android Studio 3.0 Preview Canary5
UPDATE
Although the original answer worked, I really want to turn on data-binding on my library module, where I implement some base classes using binding technique. I move them back to library module and upgrade kotlin version to the latest one 1.1.3-2. Suddenly it works also. I am not sure which one is the better but both ways work for me.
UPDATE 2
I am using com.android.tools.build:gradle:3.0.0-alpha9 and kotlin 1.1.3-2 at this time and suddenly the problem re-appear.
Now I think the problem doesn't come from Kotlin. My library module turned dataBiding { enabled=true}, but it doesn't have any layout file. I tried to create a fake layout file wrapped by <layout> tag and it works
<?xml version="1.0" encoding="utf-8"?>
<layout>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</layout>
In your gradle.properties file , add the following line
android.enableAapt2=false
Recent versions of AS3.0 switched to using AAPT2 by default.
You can disable AAPT2 in your gradle.propertіes fіle with above mentioned line of code, and continue developing on AS3 canary 4.
This was an issue for me when I had a "base" feature module without any layouts (all my actual layouts are in separate features)
Adding a dummy layout XML file in the base feature (e.g. as base/src/res/layout/dummy.xml) meant the missing directory was created and the app compiled.
(this is using com.android.tools.build:gradle:3.0.0-alpha6)
I've had the same problem, seems like a bug in Canary 4.
For now, as a workaround, I downgraded to Android Studio 3.0.0 Canary 3 (This is an archive of all Android Studio releases) and also downgraded the Android Gradle plugin to 3.0.0-alpha3:
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha3'
...
}
Updated:
Just check the Canary version after update. For that see Android Studio version just above the toolbar (File..Edit..View..line) where name at end like "Canary X".-> X is number like 3,4,5,etc.
For example suppose updated version(X) is 5.
Try to change that classpath in build.gradle(applicationName) to 3.0.0-alpha5 and sync(/Try) again:
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha5'
}
Means that updated version(X):-
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alphaX'
}

Android Studio 1.1, simple junit test setup

I have read around, there are a number of extensive answers (like this one) but the Android world evolves so fast that they seem to be a bit outdated and the official documentation still refers to Eclipse with ADT.
I am running AS 1.1 and I am trying to setup simple junit tests to run on the emulator, without Robolectric. If I don't include junit in my build.gradle, it can't find #After, #Before and #Test and I get package org.junit does not exist. Upon adding
// unit tests
androidTestCompile 'junit:junit:4.11'
the error becomes
Error:duplicate files during packaging of APK
[...]/app/build/outputs/apk/app-debug-test-unaligned.apk
Path in archive: LICENSE.txt
Origin 1: [...]/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest-core/1.3/42a25dc3219429f0e5d060061f71acb49bf010a0/hamcrest-core-1.3.jar
Origin 2: [...]/.gradle/caches/modules-2/files-2.1/junit/junit/4.11/4e031bb61df09069aeb2bffb4019e7a5034a4ee0/junit-4.11.jar
You can ignore those files in your build.gradle:
android {
packagingOptions {
exclude 'LICENSE.txt'
}
}
Following the console suggestion of excluding LICENSE.txt, it then works but it feels like a hack. So I'm wondering, am I maybe missing something? Thanks.
Android Studio unit testing support comes in 1.1 Beta 4 (release announcement) with Gradle plugin version 1.1.0-rc1.
More info in official document.
However it is experimental feature for now. E.g. it breaks installDebug gradle task.
For using JUnit in instrumentation tests there is good guide for Espresso library and another covering new AndroidJUnitRunner.
If it's any use I set up a boiler plate project allowing the use of Unit tests and Espresso tests by the use of switching build variants. You won't need the use of any third party plugins with this.
https://github.com/hitherejoe/Android-Boilerplate

Android Studio: Snapshot Dependencies Don't Update properly

I'm working With Android Studio 8.9
I've got a build.gradle with the following dependency defined:
compile ('my.program.commons:my-program-commons:0.0.2-SNAPSHOT#jar')
This dependency is stored in a private Sonatype nexus repository.
When I make changes in the my.program.commons code, I upload to nexus.
The problem is that when I then try to compile against the new SNAPSHOT android studio will fail to pick up changes.
When run from the command line gradle will build succesfully - but Android Studio will not recognize the new files.
If i do a version tick - say from 0.0.2-SNAPSHOT to 0.0.3-SNAPSHOT Android Studio will understand the new version and download and everything works out fine.
I don't want to have to do a minor version tick on every single change.
In my case, use changing = true not work for me. But configure cache changing modules solve my problem. Sample code below, add in build.gradle file:
configurations.all {
// Don't cache changing modules at all.
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
See: https://docs.gradle.org/current/userguide/dependency_management.html
You can also put a flag called "changing" that will trigger Gradle to always pull the latest, for example:
compile ('my.program.commons:my-program-commons:0.0.2-SNAPSHOT#jar') {
changing = true;
}
You need to configure the cache duration, by default gradle won't look for updates for 24 hours:
http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:controlling_caching
In my case, removing the whole <project_root>/.idea/libraries directory, was the only solution that worked. AndroidStudio stores some cached dependencies configurations there. Removing the directory makes it refetch all of them one more time.
You can write some script/task that will automate this removal and run it as part of the Gradle clean task.

Android espresso maven and gradle setup

Does any one have an example of maven setup of the new Android UI test framework called espresso ?
Quality Tools for Android now proposes both a maven and gradle setup example for android-test-kit/espresso.
To launch the espresso tests you can use either :
mvn -P espresso
gradle :android-sample-espresso-tests:connectedCheck
You'll need the Java 7 compiler (even though the code compiles with -source & -target set to 1.5). (JDK6 and JDK1.5 may have problems).
Then you'll need to setup maven-android-sdk-deployer. Instructions are here:
https://github.com/mosabua/maven-android-sdk-deployer
After that it should just be a mvn install.
Eventually the artifacts will be available as an SDK extra. This is a developer preview right now :)
Here is a 5 minutes set up of gradle setup of Espresso (in Android Studio), together with github example https://medium.com/p/c476d3b5ba45
Also take a look at Jake Wharton's Gradle-port of Espresso. That may be a better intermediary step until the original library is updated with Gradle support.
https://github.com/JakeWharton/double-espresso
Add the dependency to your build.gradle to get it working:
androidTestCompile 'com.jakewharton.espresso:espresso:1.1-r3'
Check http://mvnrepository.com/artifact/com.jakewharton.espresso/espresso for the latest version.

Categories

Resources