19

I am trying to run a unit tests which mock a child class of SQLiteOpenHelper but I am getting the following error.

java.lang.NoClassDefFoundError: android/database/sqlite/SQLiteOpenHelper

    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    ...
at org.dfhu.vpodplayer.util.JsonExporterTest.export(JsonExporterTest.java:43)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    ...

My Gradle file looks like

apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion '25.0.1'
    defaultConfig {
        applicationId "org.dfhu.vpodplayer"
        minSdkVersion 18
        targetSdkVersion 24
        versionCode 1
        versionName "1.2"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        targetCompatibility 1.7
        sourceCompatibility 1.7
    }
}


buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
  }
}

apply plugin: 'com.neenbedankt.android-apt'

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })

    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.android.support:support-v4:24.2.1'
    compile 'com.android.support:recyclerview-v7:24.2.1'

    testCompile 'junit:junit:4.12'
    testCompile 'org.powermock:powermock-api-mockito:1.6.5'
    testCompile 'org.powermock:powermock-module-junit4:1.6.5'
}

This did work before I reinstalled, Android Studio and updated to builtToolsVersion '25.0.1'.

I am looking for a way to get my android dependencies in my test runner.

Victory
  • 5,811
  • 2
  • 26
  • 45
  • 5
    Does it work with `./gradlew test`? – tynn Mar 16 '17 at 21:49
  • 2
    @tynn yes that seems to work, it downloaded a bunch of dependencies, also it now works in Android Studio. I thought clicking in the Android Studio sidebar "Gradle > [MyProjectsName] > Verfication > test" would be the same thing as the CLI, but i guess there is some difference. If you post this as an answer i will +1 and Check correct. – Victory Mar 16 '17 at 22:02
  • 1
    Thanks @tynn, worked for me. Now also works from AS – Pavel Biryukov Sep 13 '17 at 10:57

6 Answers6

24

Occasionally Android Studio does not correctly load Android classes into the classpath for testing. In our case it's usually android.os.Parcelable. But the CI always works fine.

So running ./gradlew test should always work in such occasions and with some luck fix the dependencies for Android Studio.

tynn
  • 38,113
  • 8
  • 108
  • 143
  • Thanks for the tip, this seems like a bug in Android Studio to me. – Victory Mar 16 '17 at 22:14
  • 1
    Couldn't verify it. CI helped though. – tynn Mar 16 '17 at 22:18
  • saved my day, after 1h poking around and searching for help online – Ewoks Apr 28 '17 at 11:59
  • Thank you for this answer. This worked for me. It is most likely happening because of missing dependencies. Once you run it from the terminal and it downloads dependencies, the tests start working from Android Studio too. – Abhinav Manchanda May 20 '17 at 13:11
  • @Abhinav, it happens because of a missing `mockable-android-XX.jar` file from your workspace. See my answer [here](https://stackoverflow.com/a/45087163/1071320) which explains how to fix the problem. – Adil Hussain Jul 14 '17 at 08:36
  • this may never fix the dependencies if using different gradle daemon or never work if using same daemon. – Amit Kaushik May 06 '20 at 08:14
15

(This one has been confusing and infuriating me for a while now and I'm super glad I've finally got to the bottom of it!)

The first thing to note is that after running the following command in your project...

gradle clean build

... you should see a build/generated/mockable-android-XX.jar file in your workspace. This file is generated by the mockableAndroidJar Gradle Task which is run as part of the test Gradle Task which is run as part of the build Gradle Task.

The problem occurs when this file is missing from your workspace but Gradle unfortunately estimates the mockableAndroidJar Task to be up to date and therefore skips executing it. You can verify this by running the following command...

gradle mockableAndroidJar --info

... and you'll see a message something as follows...

Skipping task ':Android:mockableAndroidJar' as it is up-to-date (took 0.001 secs).

The solution is to force run the mockableAndroidJar Gradle Task which you can do by running the following command...

gradle mockableAndroidJar --rerun-tasks

... And Voila you should now see the build/generated/mockable-android-XX.jar file reappear in your workspace and glad times your Android unit tests will be running again.

Adil Hussain
  • 30,049
  • 21
  • 112
  • 147
  • 1
    Rafael, the `mockableAndroidJar` Gradle Task may have been fixed in a recent release of the Android Plugin for Gradle so the Task may now be better at determining when the `mockable-android-XX.jar` file is missing. If this is the case then, yes, adding the `--rerun-tasks` option may no longer be necessary. – Adil Hussain May 30 '18 at 11:34
  • 3
    Seems like mockableAndroidJar has been renamed to createMockableJar since. See: https://stackoverflow.com/a/53632603/1118475 – Michał Klimczak Oct 10 '19 at 13:43
8

After facing this problem today, I'd like to share what I did to make it work again.

In your build.gradle file, add:

android {
...

testOptions {
        unitTests.returnDefaultValues = true
    }
}

and sync gradle files again. It should work now and the mockable android jar file should be generated. If you didn't have testOptions in your gradle file, just remove it and resync.

I hope it helps.

Francisco Junior
  • 1,986
  • 18
  • 25
5

You can also try invalidate cache and restart option in studio under file menu

Amit Kaushik
  • 642
  • 7
  • 13
3

For my case I just run the 'test' task from Gradle tasks, its restore everything.

enter image description here

Zakir
  • 1,305
  • 1
  • 10
  • 13
2

Well in my case it was solved by clearning app/build directory. I don't know but for some reason gradle clean command, did not do this and I had to do it manually

Hossein Shahdoost
  • 1,692
  • 18
  • 32