独自のアプリケーションクラスを使用し、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"