6

In my android app I have multidexing enabled. The app runs fine on emulators. I am using robotium for testing the app. But when I execute instrumentation test cases, sometimes the test passes, but mostly they also fail after system reboot. There is no code change between the time it passes and fails.

Default gradle configuration:

android {
        defaultConfig {
        applicationId "com.example.androidapp"
        minSdkVersion 16
        targetSdkVersion 23
        multiDexEnabled true
        testInstrumentationRunner "com.android.test.runner.MultiDexTestRunner"
        testProguardFile "proguard-test.txt"
    }
}

Also adding dependencies for test:

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

In AndroidManifest.xml I have mentioned the application tag as:

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

I have extended "android.support.multidex.MultiDexApplication" in StartupActivity. The times when the instrumentation test cases fall I get the following error:

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

The error message in logcat is:

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/AndroidRuntime﹕ Shutting down VM
W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xa628c288)

The test class looks somewhat like:

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

}

I am running the test case as an android test. I am unable to understand which dependency is messing up the code. Besides this, random failures of code are skeptical. Please help.

whitepearl
  • 634
  • 2
  • 7
  • 16
  • 1
    Members of my team have remarked similar things regarding espresso tests and multidex. More that it fails to identify that there are tests to run with multidex enabled... – BrantApps Oct 14 '15 at 18:07
  • @OceanLife Did you find any solution? – whitepearl Oct 14 '15 at 23:29
  • No we haven't, yet. It is reliable without multidex therefore I have suggested that we compile out some of the analytics libs that are bulking things up as an interim solution...just to move back to not requiring multidex. Your error message (unexpected impl) reminds me of Java's SDK incompatibility errors, so called "VerifyError" (s) ... Get some proguarding on the go to remove the bulky bits... – BrantApps Oct 15 '15 at 08:04
  • @whitepearl Possible duplicate of http://stackoverflow.com/a/28621986/1233652 ? – Alex Lipov Oct 16 '15 at 07:55
  • @AlexLipov I am not facing issue with MultiDexTestRunner. Problem is with the randomness of error. – whitepearl Oct 16 '15 at 08:52

3 Answers3

5

Found a solution for the same, that is setting dex verification and optimization parameters. You could also set dalvik.vm.dexopt-flags to v=n to have the framework pass -Xverify:none -Xdexopt:verified to disable verification.

Execute:

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

Had to wait for a few seconds after executing the commands. Instrumentation test with multidexing run smoothly post that.

whitepearl
  • 634
  • 2
  • 7
  • 16
1

For gradle plugin 1.5.0 you could use this workaround in your 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")
            }
        }
    }
}
x2on
  • 2,267
  • 3
  • 24
  • 44
0

In case you're using gradle plugin above 1.4.0-beta3. Multi-Dex support was added to gradle plugin, which means that multidex and multidex-instrumentation dependencies are already included and you don't have to specify them explicitly. Unfortunately, it seems to be buggy on pre-Lollipop devices, looks like different versions of MultiDexApplication are used for the target and test application. As a result Instrumentation fails to run and logcat gives you something similar to this:

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

The solution would be to use 1.3.1 gradle plugin and be careful to explicitly specify multidex and multidex-instrumentation (in case you also need this) dependencies of the same version. You also probably want to use AndroidJUnitRunner, since it has built-in multi-dex support.

Feel free to star the related issue: https://code.google.com/p/android/issues/detail?id=194609

Ghedeon
  • 1,643
  • 1
  • 18
  • 30