启用multidex后,仪器测试会随机失败。

6
在我的Android应用中,开启了multidex。该应用在模拟器上运行良好。我正在使用Robotium来测试应用程序。但是,在执行仪器测试用例时,有时测试会通过,但大多数情况下在系统重新启动后也会失败。在测试通过和失败之间没有代码更改。
默认的Gradle配置:
android {
        defaultConfig {
        applicationId "com.example.androidapp"
        minSdkVersion 16
        targetSdkVersion 23
        multiDexEnabled true
        testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
        testProguardFile "proguard-test.txt"
    }
}

另外还需要为测试添加依赖:

androidTestCompile fileTree(dir: 'libs', include:'robotium-solo-5.3.0.jar') 

androidTestCompile ('com.android.support:multidex-instrumentation:1.0.1') {
         exclude group: 'com.android.support', module: 'multidex' }

在AndroidManifest.xml中,我将应用程序标签声明为:

<application
        android:name="StartupActivity"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name" ...../>

我在StartupActivity中扩展了“android.support.multidex.MultiDexApplication”。当仪器测试案例失败时,我会得到以下错误:

INSTRUMENTATION_RESULT: shortMsg=java.lang.IllegalAccessError
INSTRUMENTATION_RESULT: longMsg=java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
INSTRUMENTATION_CODE: 0

日志中的错误信息为:
W/dalvikvm﹕ Class resolved by unexpected DEX: Lcom/example/androidapp/StartupActivity;(0xa695df08):0x9910e000 ref [Landroid/support/multidex/MultiDexApplication;] Landroid/support/multidex/MultiDexApplication;(0xa695df08):0x99a2c000
W/dalvikvm﹕ (Lcom/example/androidapp/StartupActivity; had used a different Landroid/support/multidex/MultiDexApplication; during pre-verification)
W/dalvikvm﹕ Unable to resolve superclass of Lcom/example/androidapp/StartupActivity; (540)
W/dalvikvm﹕ Link of class 'Lcom/example/androidapp/StartupActivity;' failed
D/AndroidRuntimeShutting down VM
W/dalvikvmthreadid=1: thread exiting with uncaught exception (group=0xa628c288)

测试类看起来有些像:
public class HelloActivityTest extends ActivityInstrumentationTestCase2<HelloActivity> {
private Solo solo;
public HelloActivityTest() {
    super(HelloActivityTest.class);
}
  @Override
  public void setUp() throws Exception {
    setActivityInitialTouchMode(false);
    solo = new Solo(getInstrumentation(), getActivity());
  }

  public void test1() {}

  public void test2() {}

}

我正在运行一个Android测试用例。我无法理解哪个依赖项搞乱了代码。此外,代码的随机失败令人怀疑。请帮忙。


1
我的团队成员也提到了关于 Espresso 测试和 multidex 的类似问题。更重要的是,它无法识别启用 multidex 后需要运行的测试。 - BrantApps
@OceanLife 你找到任何解决方案了吗? - whitepearl
我们还没有这样做,但是它在没有multidex的情况下很可靠,因此我建议我们编译一些分析库来解决问题……只是为了回到不需要multidex的状态。你的错误信息(意外的impl)让我想起了Java的SDK不兼容错误,所谓的“VerifyError”(s)……开始进行一些proguarding操作以去除臃肿的部分...... - BrantApps
@whitepearl 可能是 https://dev59.com/zl4c5IYBdhLWcg3wUI4N#28621986 的重复问题? - Alex Lipov
@AlexLipov,我不是在处理MultiDexTestRunner的问题。问题在于错误的随机性。 - whitepearl
3个回答

5

找到了一个解决方案,即设置dex验证和优化参数。您还可以将dalvik.vm.dexopt-flags设置为v=n,以使框架传递-Xverify:none -Xdexopt:verified以禁用验证。

执行:

adb shell setprop dalvik.vm.dexopt-flags v=n,o=v
adb shell stop installd
adb shell start installd

执行命令后需要等待几秒钟。在多dex情况下运行的仪器测试顺利进行。


谢谢你,这里运行良好。希望 Google 能尽快修复这个问题。 - x2on

1
"

对于Gradle插件1.5.0,您可以在build.gradle中使用此解决方法:

"
// Workaround for Multidex bug in gradle-android-plugin
// Replace Multidex dependency with some dummy dependency to avoid dex problems
// @see https://code.google.com/p/android/issues/detail?id=194609
project.getConfigurations().all { config ->
    if (config.name.contains("AndroidTest")) {
        config.resolutionStrategy.eachDependency { DependencyResolveDetails details ->
            if (details.requested.name == "multidex") {
                details.useTarget("de.felixschulze.teamcity:teamcity-status-message-helper:1.2")
            }
        }
    }
}

对我来说还是不起作用,这段代码放在我的项目的 build.gradle 文件中吗? - Gaston Flores
是的,只需将它添加到您的 build.gradle 中,它就应该可以工作了。也许您还有其他依赖问题。 - x2on

0

如果您使用的Gradle插件版本高于1.4.0-beta3,则已添加了对Gradle插件的Multi-Dex支持,这意味着multidexmultidex-instrumentation依赖项已经包含在内,您无需明确指定它们。不幸的是,在老版本的设备上看起来有一些问题,似乎目标和测试应用程序使用了不同版本的MultiDexApplication。因此,导致Instrumentation无法运行,并且logcat会给出类似于以下内容的信息:

W/dalvikvm: Class resolved by unexpected DEX: Lcom/example/dexproof/App;(0x43893f90):0x64d46000 ref [Landroid/support/multidex/MultiDexApplication;] Landroid/support/multidex/MultiDexApplication;(0x43893f90):0x5de01000
W/dalvikvm: (Lcom/example/dexproof/App; had used a different Landroid/support/multidex/MultiDexApplication; during pre-verification)
W/dalvikvm: Unable to resolve superclass of Lcom/example/dexproof/App; (457)
W/dalvikvm: Link of class 'Lcom/example/dexproof/App;' failed
E/AndroidRuntime: java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation

解决方案是使用1.3.1版本gradle插件并小心地明确指定相同版本的multidexmultidex-instrumentation(如果你也需要它们)。你还可能想使用AndroidJUnitRunner,因为它具有内置的多dex支持。
请随意给相关问题打星:https://code.google.com/p/android/issues/detail?id=194609

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接