Robolectric with ActiveAndroid setup nullpointerexception on ActiveAndroid$ReflectionUtils
Asked Answered
G

1

2

I am trying to implement robolectric testing in an existing app. I can run simple static tests but when I add testing with ActiveAndroid I get NullPointerExceptions, I think ActiveAndroid can not be found when the unit test is being run.

Im not sure maybe there are some configurations for ActiveAndroid for Robelectric unit testing. Kindly help me on this one.

This is the project structure:

MainApp
-src/main
-src/test

LibraryApp
-src/main/models <--- here are my models and classes for active android
-libs/activeandroid-3.0.jar <---- the active android jar file

I imported ActiveAndroid-3.0.jar in the Library App.

Here are the build.gradle files:

MainApp build.gradle

android {
compileSdkVersion 21
buildToolsVersion "22.0.0"

defaultConfig {
    applicationId "com....."
    minSdkVersion 18
    targetSdkVersion 21
    versionCode 1
    versionName "1.0"

    // Enabling multidex support.
    multiDexEnabled true

    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

dexOptions {
    preDexLibraries = false
}

sourceSets {
    main {
        java {
            exclude 'com/google/gson/annotations/Expose.class'
        }
    }
}

lintOptions{
    abortOnError false
}
packagingOptions{
    exclude 'META-INF/NOTICE.txt'
    exclude 'META-INF/LICENSE.txt'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile files('libs/gcm.jar')
compile 'com.android.support:multidex:1.0.1'
compile 'joda-time:joda-time:2.9.1'
androidTestCompile 'junit:junit:4.12'
testCompile 'junit:junit:4.12'
compile 'com.facebook.fresco:fresco:0.7.0+'
compile 'com.github.bluejamesbond:textjustify-android:2.1.0'
compile files('libs/activeandroid-3.0.jar')
compile 'com.google.android.gms:play-services:7.5.0'
compile 'com.jakewharton:butterknife:7.0.1'
compile files('libs/FlurryAnalytics-5.5.0.jar')
compile project(':app')
androidTestCompile 'com.android.support.test:runner:0.3'
testCompile 'com.android.support.test:runner:0.3'

androidTestCompile 'com.android.support.test:rules:0.3'
testCompile 'com.android.support.test:rules:0.3'
// Set this dependency to build and run Espresso tests
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2'
// Set this dependency to build and run UI Automator tests
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
//compile 'com.squareup.retrofit:retrofit:2.0.0-beta1'

//classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.0.2'
compile 'com.github.jakob-grabner:Circle-Progress-View:v1.2.2'
compile('com.crashlytics.sdk.android:crashlytics:2.5.5@aar') {
    transitive = true;
}
testCompile "org.robolectric:robolectric:3.0-rc3"
testCompile 'junit:junit:4.12'
testCompile "org.robolectric:shadows-multidex:3.0"
}

LibraryApp build.gradle

apply plugin: 'com.android.library'

android {
compileSdkVersion 21
buildToolsVersion "22.0.0"

defaultConfig {
    minSdkVersion 18
    targetSdkVersion 22
    versionCode 1
    versionName "1.0"

    // Enabling multidex support.
    multiDexEnabled false
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
dexOptions {
    preDexLibraries = false
}

packagingOptions{
    exclude 'META-INF/NOTICE.txt'
    exclude 'META-INF/LICENSE.txt'
    exclude 'META-INF/LICENSE'
    exclude 'META-INF/NOTICE'
}

configure(android.lintOptions) {
    abortOnError false
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])

compile 'com.balysv.materialmenu:material-menu-toolbar:1.5.4'
compile 'org.lucasr.twowayview:twowayview:0.1.4'
compile files('libs/gson-2.3.1.jar')
compile 'org.apache.httpcomponents:httpmime:4.2.3'
compile files('libs/activeandroid-3.0.jar')
compile 'com.google.code.gson:gson:2.3.1'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.scottyab:aescrypt:0.0.1'
compile 'com.android.support:multidex:1.0.1'

testCompile "org.robolectric:robolectric:3.0-rc3"
testCompile 'junit:junit:4.12'
testCompile "org.robolectric:shadows-multidex:3.0"
}

Here is my unit test,

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP, shadows= {ShadowMultiDex.class})
public class MyActivityTest {
    Activity activity = null;
    @Before
    public void init(){
    }
    @Test
    public void getMillisecondFromHourTest(){
    }
}

If I run the unit test with a custom Application class where ActiveAndroid.initialize(this); where is not being called my unit tests run (only those static asserts).

If I use an Application class the calls ActiveAndroid.initialize(this); this happens:

    java.lang.NullPointerException
    at dalvik.system.DexFile$DFEnum.hasMoreElements(DexFile.java:262)
    at com.activeandroid.ReflectionUtils.getParsers(ReflectionUtils.java:152)
    at com.activeandroid.Registry.initialize(Registry.java:100)
    at com.activeandroid.ActiveAndroid.initialize(ActiveAndroid.java:8)
    at com.activeandroid.app.Application.onCreate(Application.java:9)
    at      com.MyApplication.onCreate(MyApplication.java:28 1)
    at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:140)
    at   org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:433)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:240)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

java.lang.RuntimeException: java.lang.NullPointerException
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:244)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.NullPointerException
    at dalvik.system.DexFile$DFEnum.hasMoreElements(DexFile.java:262)
    at com.activeandroid.ReflectionUtils.getParsers(ReflectionUtils.java:152)
    at com.activeandroid.Registry.initialize(Registry.java:100)
    at com.activeandroid.ActiveAndroid.initialize(ActiveAndroid.java:8)
    at com.activeandroid.app.Application.onCreate(Application.java:9)
    at com.MyApplication.onCreate(MyApplication.java:281)
    at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:140)
    at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:433)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:240)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    ... 1 more

By the way. I have this in my MyApplication.class also

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}
Gunthar answered 9/1, 2016 at 15:51 Comment(0)
C
0

Ah, we had a similar issue. We resolved it by next Robolectric feature http://robolectric.org/custom-test-runner/

We moved created method:

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    installMultiDex();
}

protected void installMultiDex() {
    MultiDex.install(this);
}

And overrided it in the test application:

@Override
protected void installMultiDex() {
    //don't do anything
}
Colorist answered 9/1, 2016 at 16:19 Comment(5)
by the way Eugen, I was thinking the shadow ShadowMultiDex.class is the one responsible for doing that. Is that correct? I also tried your suggestion before and again today, but still it always fails on ActiveAndroid.initialize(this).Gunthar
Use the similar trick for ActiveAndroid. You don't need it while testing classes one by oneColorist
Hi Eugen, Im not sure what you mean. I need ActiveAndroid to be setup for me to test database queries. Can you please guide me on how to do it on ActiveAndroid.Gunthar
Sorry for the delay in the answer. I've checked multidex shadow and yes it is excatly what you said. So question is open why it doesn't work, maybe because of api 21?Colorist
I would hide ActiveAndroid behind own storage component. In this case your app will be free from it except the component code and there you can instantiate itColorist

© 2022 - 2024 — McMap. All rights reserved.