Android java.lang.NoClassDefFoundError:R $ string

jon*_*ney 5 android unit-testing robolectric robolectric-gradle-plugin

每当我运行单元测试时,我在尝试从自定义config.xml文件中检索字符串值时会收到此错误.

背景:

该项目本身是一个库apk项目,使用和引用另一个库APK项目.

当项目本身尝试启动一个新对象时,会发生错误,该对象是引用的库apk项目中包含的超类的子类.

该问题在下面解释了更多

因错误而失败的特定代码行是下面定义的静态变量:

  protected static final String ANDROID_CONFIG_ID =  LibraryApplication.getApplication().getString(R.string.api_checkout_config_id_override);
Run Code Online (Sandbox Code Playgroud)

它失败并出现以下错误:

java.lang.NoClassDefFoundError: com/jon/commonlib/R$string
Run Code Online (Sandbox Code Playgroud)

如果您想知道,commonLib是引用的库apk.

这是我的单元测试

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, manifest=Config.NONE)
public class TestSearchShows {

    @Test
    public void testSearchJsonFile(){
        EventsTestHelper testHelper = new EventsTestHelper(RuntimeEnvironment.application);

        try {
            ShowsList showList = testHelper.getShowList(new SearchEvent());

            if(showList.getShows().size() < 0){
                Assert.fail("show list is empty");
            }

        } catch (IOException e) {
            e.printStackTrace();
            Assert.fail(e.toString());
        }
    }


}
Run Code Online (Sandbox Code Playgroud)

EventsTestHelper是名为NetworkHelper的超类的子类,如下所示:

public abstract class NetworkHelper<T, P, S> implements NetworkConstants {

protected static final String ANDROID_CONFIG_ID = LibraryApplication.getApplication().getString(R.string.api_checkout_config_id_override);

//other stuff ....

}
Run Code Online (Sandbox Code Playgroud)

我使用robolectric版本3.0最新的运行,我的单元测试.

如果我要运行代码并调用并启动子类,它可以正常工作,没有崩溃

编辑:以下是我的构建gradle文件的片段

apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.library'
apply plugin: 'crashlytics'


buildscript {
    repositories {
        jcenter()
        mavenCentral()
        maven { url 'http://download.crashlytics.com/maven' }
        maven { url 'http://www.testfairy.com/maven' }

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.1.0'
        classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.+'
        classpath 'com.crashlytics.tools.gradle:crashlytics-gradle:1.+'
        classpath 'com.testfairy.plugins.gradle:testfairy:1.+'

    }
}

repositories {
    mavenCentral()
    maven { url 'http://download.crashlytics.com/maven' }
    maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
    flatDir {
        dirs 'libs'
    }
}

android {
    compileSdkVersion 19
    buildToolsVersion "22.0.1"
    def package_namespace = "com.jonney.moduleApp"

   defaultConfig {
        minSdkVersion 14
        testApplicationId "com.jonney.moduleApp"
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
 productFlavors {
        //testing {
        //}
        local {
        }
        mock {
        }
        qa {
        }
        //qa4 {
        //}
        production {
        }
    }

    sourceSets {



        local {
            res.srcDir 'build-config/local/res'
        }
        testing {
            res.srcDir 'build-config/testing/res'
        }
        mock {
            res.srcDir 'build-config/mock/res'
        }
        qa {
            res.srcDir 'build-config/qa/res'
        }
        qa4 {
            res.srcDir 'build-config/qa4/res'
        }
        staging {
            res.srcDir 'build-config/staging/res'
            test.java.srcDirs += 'src/main/java'
        }
        production {
            res.srcDir 'build-config/production/res'
            test.java.srcDirs += 'src/main/java'
            test.java.srcDirs += "build/generated/source/r/production"
            test.java.srcDirs += "build/generated/source/buildConfig/production"
        }

    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:19.1.+'
    compile 'com.google.code.gson:gson:2.3'
    testCompile('org.robolectric:robolectric:3.0') {
        exclude group: 'commons-logging', module: 'commons-logging'
        exclude group: 'org.apache.httpcomponents', module: 'httpclient'
    }
    compile 'com.fasterxml.jackson:jackson-parent:2.5'
    compile 'com.squareup:otto:1.3.6'
    compile 'com.jakewharton:butterknife:6.1.0'
    compile 'com.sothree.slidinguppanel:library:3.0.0'
    compile 'com.crashlytics.android:crashlytics:1.+'
    compile 'com.mcxiaoke.volley:library-aar:1.0.0'
    compile "joda-time:joda-time:2.4"
    testCompile('junit:junit:4.12') {
        exclude module: 'hamcrest'
        exclude module: 'hamcrest-core'
    }
    testCompile 'org.hamcrest:hamcrest-all:1.3'
    compile 'com.sothree.slidinguppanel:library:3.0.0'
    compile 'com.squareup:otto:1.3.6'
    compile 'com.squareup.okhttp:okhttp:2.3.0'
    testCompile 'org.apache.maven:maven-ant-tasks:2.1.3'

    compile 'com.google.android.gms:play-services:7.0.0'

    compile 'com.android.support:multidex:1.0.0'

    compile(name: 'commonLib 1.0 1', ext: 'aar')
    testCompile(name: 'commonLib-1.0 1', ext: 'aar')
}
Run Code Online (Sandbox Code Playgroud)

编辑:我还尝试手动创建一个复制每个依赖项的r类的任务.

    afterEvaluate { project ->
        android.libraryVariants.each { variant ->
            // workaround for missing R class for aar dependencies
            def copyTaskName = "copy${variant.name.capitalize()}AppCompat"
            def copyTaskNameTwo = "copy${variant.name.capitalize()}commonlib"
            task(copyTaskName, type:Copy) {
                dependsOn "process${variant.name.capitalize()}Resources"
                from { "build/generated/source/r/${variant.dirName}/$package_namespace_path" }
                into { "build/generated/source/r/${variant.dirName}/com/jon/commonlib" }
//                into { "src/test/java/android/support/v7/appcompat" }
                include 'R.java'
                filter { line -> line.contains("package ${package_namespace};") ? 'package android.support.v7.appcompat;' : line }
                outputs.upToDateWhen { false }
            }
            task(copyTaskNameTwo, type:Copy) {
                dependsOn "process${variant.name.capitalize()}Resources"
                from { "build/generated/source/r/${variant.dirName}/$package_namespace_path" }
                into { "build/generated/source/r/${variant.dirName}/android/support/v7/appcompat" }
//                into { "src/test/java/android/support/v7/appcompat" }
                include 'R.java'
                filter { line -> line.contains("package ${package_namespace};") ? 'package com.jon.commonlib;' : line }
                outputs.upToDateWhen { false }
            }
            System.out.println("adding ${copyTaskName} build/generated/source/r/${variant.dirName}/$package_namespace_path ")
            println("basename =  ${variant.baseName}")
            println("directory name =  ${variant.dirName}")
            tasks.getByName("compile${variant.name.capitalize()}UnitTestJava") dependsOn copyTaskName
        }
    }
Run Code Online (Sandbox Code Playgroud)

亲切的问候

jonnney

zec*_*zec 0

您是否将库包含在测试类路径中?

 dependencies {
    androidTestCompile(<reference to commonLib>)
 }
Run Code Online (Sandbox Code Playgroud)