LoginSignup
8
6

More than 5 years have passed since last update.

Robolectric と Multidex でテストが落ちる問題の対応

Posted at

独自のアプリケーションクラスを使用し、attachBaseContext 内で Multidex.install を呼び出している場合に例外を吐いてテストが落ちることがありました。

class TwitcastingDebugApplication: TwitcastingApplication() {

    override fun attachBaseContext(base: Context?) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }

}

実際に吐いた例外は以下

java.lang.RuntimeException: Multi dex installation failed (/Users/yusukehata/Project/TwitcastingViewer-v2/app/. (Is a directory)).
    at android.support.multidex.MultiDex.install(MultiDex.java:178)
    at com.kuwapp.twitcastingviewer_v2.TwitcastingDebugApplication.attachBaseContext(TwitcastingDebugApplication.kt:10)
    at android.app.Application.attach(Application.java:189)
    at org.robolectric.util.ReflectionHelpers.callInstanceMethod(ReflectionHelpers.java:231)
    at org.robolectric.android.ApplicationTestUtil.attach(ApplicationTestUtil.java:30)
    at org.robolectric.android.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:126)
    at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:290)
    at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:203)
    at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:109)
    at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:36)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:63)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy3.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:377)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)

もちろんテストには Multidex 不要なので落ちないでほしい。。

Shadow を定義して対応する

Multidex.install を呼び出すと落ちるので、Shadow を作成し、Multidex.install の際に何もしないようにします。
Kotlin だけどこんな感じ。

@Implements(MultiDex::class)
class ShadowMultidex {

    companion object {

        @JvmStatic
        @Implementation
        fun install(context: Context) {

        }

    }

}

そしてテストクラスに Shadow を指定すればOK

@RunWith(RobolectricTestRunner::class)
@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.N_MR1), shadows = arrayOf(ShadowMultidex::class))
class HogeTest

実は公式で用意されている

実は ShadowMultiDex.java は Robolectric で用意されています。
そのため、build.gradle の dependencies に以下を追加すれば大丈夫です。

testCompile "org.robolectric:shadows-multidex:3.3.2"
8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6