App无法进行Robolectric单元测试

时间:2015-03-12 23:59:22

标签: android robolectric multidex

我有一个Android应用程序,它使用了很多库,我现在需要使用MultiDex-ing。不幸的是,当我引入多索引时,我现有的Robolectric单元测试不再运行甚至启动。在我加入多德兴之前,他们跑得很好。

参考github上的原始帖子

https://github.com/robolectric/robolectric/issues/1328

并提出解决方案

https://github.com/robolectric/robolectric/pull/1457

我仍然无法让我的单元测试运行。

以下是我的build.gradle文件版本1的片段,其中我试图获取最新的robolectric快照以及我可以在我的代码中使用的ShadowMultiDex.java。

buildscript {
    repositories {
        mavenCentral()
        maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
    }
    dependencies {
        classpath 'org.robolectric:robolectric-gradle-plugin:0.14.+'
    }
}

repositories {
    maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}

apply plugin: 'android'
apply plugin: 'robolectric'
apply plugin: 'com.android.application'

...

android {
    // other things
    ...

    sourceSets {
        androidTest {
            setRoot('src/test')
            resources.srcDirs = ['assets']
        }
    }
}

dependencies {
    // regular
    ...

    // unit testing
    androidTestCompile fileTree(dir: 'libs/test', include: '*.jar')
    androidTestCompile('com.squareup:fest-android:1.0.+') {
        exclude group: 'com.android.support'
    }
    androidTestCompile 'com.google.dexmaker:dexmaker:1.+'


    androidTestCompile('junit:junit:4.11') {
        exclude module: 'hamcrest-core'
    }
    androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
    androidTestCompile 'org.mockito:mockito-core:1.9.5'
    androidTestCompile 'org.robolectric:android-all:+'
    androidTestCompile 'org.robolectric:shadows-multidex:3.0-SNAPSHOT'
    androidTestCompile('org.robolectric:robolectric:3.0-SNAPSHOT') {
        exclude module: 'classworlds'
        exclude module: 'commons-logging'
        exclude module: 'httpclient'
        exclude module: 'maven-artifact'
        exclude module: 'maven-artifact-manager'
        exclude module: 'maven-error-diagnostics'
        exclude module: 'maven-model'
        exclude module: 'maven-project'
        exclude module: 'maven-settings'
        exclude module: 'plexus-container-default'
        exclude module: 'plexus-interpolation'
        exclude module: 'plexus-utils'
        exclude module: 'wagon-file'
        exclude module: 'wagon-http-lightweight'
        exclude module: 'wagon-provider-api'
    }

我还创建了一个包含内容

的org.robolectric.Config.properties文件
shadows=org.robolectric.shadows.ShadowMultiDex

通过上面的内容,我继续进入我的测试类并在我的小测试中包含ShadowMultiDex。

@RunWith(RobolectricGradleTestRunner.class)
@Config(shadows = {ShadowMultiDex.class})
public class AppVersionTest extends MyBaseTest {

    @Before
    @Override
    public void setUp() throws Exception {
        super.setUp();
    }

    @Test
    public void testIsDefaultTrue() {
        // setup
        AppVersion appVersion = new AppVersion(null);

        // run
        boolean result = appVersion.isDefault();

        // verify
        assertThat(result).isTrue();
    }
}

当我进行单元测试时,我仍然会得到一个NullPointerException来设置Application及其元数据。我正在寻找的是看看别人做了什么来实际修复这个问题并让它运行。

1 个答案:

答案 0 :(得分:0)

您是否尝试过使用Android Unit Testing Support + Multidex + Robolectric + Mockito?

我让它做了一些小改动:

  • 我无法通过AS运行单元测试,只能运行命令行。
  • 需要使用Mockito 1.9.0版本,因为版本1.9.5与Robolectric + Multidex不兼容。 (如果你使它工作,请分享:))。我在仪器测试中使用的是1.9.5版本。
  • 在我的MainApplication上实现了attachBaseContext,如下所示:
  @Override
  protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    try{
        MultiDex.install(this);
    } catch (RuntimeException ignore){
        //Multidex error when running Robolectric tests => ignore.
    }
  } 
  • 必须排除重复的依赖关系(check this post

  • 我使用自定义的Robolectric运行器,我刚刚实现了它的构造函数(设置资源文件的正确路径):

public RobolectricCustomRunner(Class<?> testClass) throws InitializationError     {
    super(testClass);
    String buildVariant = (BuildConfig.FLAVOR.isEmpty() ? "" : BuildConfig.FLAVOR+ "/") + BuildConfig.BUILD_TYPE;
    String intermediatesPath = "build/intermediates";

    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);
}

希望它有所帮助。