21

Adding Multi dex support with the support v4-r21 using gradle def (https://plus.google.com/+IanLake/posts/JW9x4pcB1rj)

apply plugin: 'com.android.application'

android {
compileSdkVersion 19
buildToolsVersion "20.0.0"

defaultConfig {
    applicationId "info.osom.multidex"
    minSdkVersion 19
    targetSdkVersion 19
    versionCode 1
    versionName "1.0"
}
buildTypes {
    release {
        runProguard false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

dexOptions {
    preDexLibraries = false
}

afterEvaluate {
    tasks.matching {
    it.name.startsWith('dex')
    }.each { dx ->
    if (dx.additionalParameters == null) {
        dx.additionalParameters = []
    }
    dx.additionalParameters += '--multi-dex'
    dx.additionalParameters += "--main-dex-list=$projectDir/multidex.keep".toString()
}

Now this works for the app itself and I'm able to build and deploy but when I run a robolectric test for my Application class, I get a failure from ZipUtils (which is caught in MultiDex.java). The other tests are running fine. Here is the trace -

Caused by: java.lang.RuntimeException: Multi dex installation failed (/Users/Code/android-code/android/. (Is a directory)). at android.support.multidex.MultiDex.install(MultiDex.java:178) at android.support.multidex.MultiDexApplication.attachBaseContext(MultiDexApplication.java:39) at android.app.Application.attach(Application.java:181) at org.fest.reflect.method.Invoker.invoke(Invoker.java:112) at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:155) at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:430) at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:236) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:177) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:49) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:69) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:48) at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) at com.sun.proxy.$Proxy2.processTestClass(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:105)

Rickster
  • 1,393
  • 3
  • 13
  • 19

3 Answers3

51

Add multi-dex shadow as your dependency:

testCompile "org.robolectric:shadows-multidex:3.0"

This will mock MultiDex.install call and do nothing, since there are no dex in Robolectric

Shubham Chaudhary
  • 47,722
  • 9
  • 78
  • 80
  • 4
    helped, thanks. just need to make sure the version in this line is identical to the one in: testCompile 'org.robolectric:robolectric:3.0' (Otherwise it wont work) – user2924714 Nov 01 '16 at 10:11
  • This worked for me! as above said, make sure your versions match. – Ryan Newsom Nov 03 '16 at 20:51
4

It's a known bug, wait for a fix: https://github.com/robolectric/robolectric/issues/1328

MLProgrammer-CiM
  • 17,231
  • 5
  • 42
  • 75
3

You needs to create an Application class that inherits from MultiDexApplication attachBaseContext (Context) is Override, and crush an exception if run on JavaVM.

  import android.content.Context;
    import android.support.multidex.MultiDexApplication;

    public class Application extends MultiDexApplication {

       @Override
       protected void attachBaseContext(Context base) {
          try {
            super.attachBaseContext(base);
          } catch (Exception e) {
            String vmName = System.getProperty("java.vm.name");
            if (!vmName.startsWith("Java")) {
               throw e;
            }
          }
       }
    }
Hoshouns
  • 2,420
  • 23
  • 24