带外部库的Robolectric NoClassDefFoundError

时间:2015-04-03 00:36:35

标签: java android testing robolectric

我的所有项目活动都继承自CustomActivity,这是我创建的外部库,可以帮助我处理常见的事情。

问题是当我尝试使用robolectric测试该活动时,我收到此错误:

java.lang.NoClassDefFoundError: br/com/androidcore/activity/CustomActivity

有什么想法吗?我应该影子吗?我应该参考一些Robolectric配置吗?

这是我的应用构建文件:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "br.com.boozeprice"
        minSdkVersion 14
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    defaultConfig {
        testInstrumentationRunner "com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner"
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.android.support:support-v4:21.0.3'

    compile project(':androidcore')
    compile project(':persistencecore')

    testCompile 'junit:junit:4.12'
    testCompile 'org.robolectric:robolectric:2.4'
}

编辑,添加额外信息:

我的gradle版本:

dependencies {
    classpath 'com.android.tools.build:gradle:1.1.3'
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}

我的测试:

@RunWith(CustomRobolectricRunner.class)
public class IntegrationTest {
    @Test
    public void testActivity() {
        Activity activity = Robolectric.setupActivity(MainActivity.class);
        TextView txt = (TextView) activity.findViewById(R.id.txtMain);
        String result = txt.getText().toString();
        assertThat(result, equalTo("Test"));
    }
}

我的CustomRunner:

 public class CustomRobolectricRunner extends RobolectricTestRunner {
    public CustomRobolectricRunner(Class<?> testClass)
            throws InitializationError {
        super(testClass);
    }

    @Override
    protected AndroidManifest getAppManifest(Config config) {
        String path = "src/main/AndroidManifest.xml";

        // android studio has a different execution root for tests than pure gradle
        // so we avoid here manual effort to get them running inside android studio
        if (!new File(path).exists()) {
            path = "app/" + path;
        }

        config = overwriteConfig(config, "manifest", path);
        return super.getAppManifest(config);
    }

    protected Config.Implementation overwriteConfig(
            Config config, String key, String value) {
        Properties properties = new Properties();
        properties.setProperty(key, value);
        return new Config.Implementation(config,
                Config.Implementation.fromProperties(properties));
    }

    @Override
    protected SdkConfig pickSdkVersion(
            AndroidManifest appManifest, Config config) {
        // current Robolectric supports not the latest android SDK version
        // so we must downgrade to simulate the latest supported version.
        config = overwriteConfig(config, "emulateSdk", "18");
        return super.pickSdkVersion(appManifest, config);
    }
}

我的主要活动:

public class MainActivity extends CustomActivity

自定义活动:

public abstract class CustomActivity extends Activity

提前致谢

1 个答案:

答案 0 :(得分:-1)

基本问题是robolectric不了解您的图书馆资源。但这可以修复......

选项1:将robolectric更新为3.0-rc2

删除自定义跑步者。有一个新类RobolectricGradleTestRunner可以修复库依赖项的资源加载

选项2:使用RobolectricGradleTestRunner的解决方法

删除自定义robolectric runner中的所有代码并添加

public CustomRobolectricRunner(Class<?> testClass) throws InitializationError {
    super(testClass);
    String buildVariant = (BuildConfig.FLAVOR.isEmpty() ? "" : BuildConfig.FLAVOR+ "/") + BuildConfig.BUILD_TYPE;
    String intermediatesPath = getClass().getResource("").toString().replace("file:", "");
    System.out.println(intermediatesPath);
    intermediatesPath = intermediatesPath.substring(0, intermediatesPath.indexOf("/classes"));

    System.setProperty("android.package", BuildConfig.APPLICATION_ID);
    System.setProperty("android.manifest", intermediatesPath + "/manifests/full/" + buildVariant + "/AndroidManifest.xml");
    System.setProperty("android.resources", intermediatesPath + "/res/" + buildVariant);
    System.setProperty("android.assets", intermediatesPath + "/assets/" + buildVariant);
}

有些例子请访问: