【问题标题】:Robolectric with ActiveAndroid setup nullpointerexception on ActiveAndroid$ReflectionUtils在 ActiveAndroid$ReflectionUtils 上使用 ActiveAndroid 设置 nullpointerexception 的 Robolectric
【发布时间】:2016-01-09 15:51:04
【问题描述】:

我正在尝试在现有应用中实施 robolectric 测试。我可以运行简单的静态测试,但是当我使用 ActiveAndroid 添加测试时,我得到 NullPointerExceptions,我认为在运行单元测试时找不到 ActiveAndroid。

我不确定 ActiveAndroid 是否有一些配置用于 Robelectric 单元测试。请帮我解决这个问题。

这是项目结构:

主应用程序
-src/main
-src/测试

图书馆应用
-src/main/models -libs/activeandroid-3.0.jar

我在 Library App 中导入了 ActiveAndroid-3.0.jar。

这里是 build.gradle 文件:

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"
}

这是我的单元测试,

@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(){
    }
}

如果我使用自定义应用程序类运行单元测试,其中 ActiveAndroid.initialize(this); 未调用我的单元测试运行(仅那些静态断言)。

如果我使用 Application 类调用 ActiveAndroid.initialize(this); 会发生这种情况:

    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

顺便说一句。我的 MyApplication.class 中也有这个

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}

【问题讨论】:

    标签: android unit-testing robolectric activeandroid


    【解决方案1】:

    啊,我们遇到了类似的问题。我们通过下一个 Robolectric 功能 http://robolectric.org/custom-test-runner/

    解决了这个问题

    我们移动了创建的方法:

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

    并在测试应用程序中覆盖它:

    @Override
    protected void installMultiDex() {
        //don't do anything
    }
    

    【讨论】:

    • 顺便说一下 Eugen,我在想影子 ShadowMultiDex.class 是负责这样做的人。那是对的吗?我今天也反复尝试过你的建议,但它仍然在 ActiveAndroid.initialize(this) 上失败。
    • ActiveAndroid 使用类似的技巧。逐个测试类时不需要它
    • 嗨,Eugen,我不确定你的意思。我需要为我设置 ActiveAndroid 来测试数据库查询。能否请您指导我如何在 ActiveAndroid 上进行操作。
    • 抱歉,回答延迟。我已经检查了 multidex 阴影,是的,这正是你所说的。所以问题是开放的,为什么它不起作用,可能是因为 api 21?
    • 我会将 ActiveAndroid 隐藏在自己的存储组件后面。在这种情况下,您的应用程序将没有它,除了组件代码,您可以在那里实例化它
    猜你喜欢
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多