Data binding ライブラリを使っている Android アプリを Espresso と組み合わせて (?) instrumented tests (./gradlew connectedAndroidTest
) を実行すると、以下のような例外でテストに失敗することがある。
java.lang.ClassCastException: java.lang.String cannot be cast to <our.app.DataBindingType>
発生する問題
私が実際に遭遇したのは以下のようなエラー。
your.app.package.id.TargetActivityTest > yourTestMethodName[Nexus 5 - 6.0.1] FAILED
java.lang.RuntimeException: Unable to start activity ComponentInfo{your.app.package.id/your.app.package.id.TargetActivity}: java.lang.ClassCastException: java.lang.String cannot be cast to your.app.package.id.databinding.ActivityTargetBinding
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
Tests on Nexus 5 - 6.0.1 failed: Instrumentation run failed due to 'java.lang.ClassCastException'
:app:connectedDebugAndroidTest FAILED
報告
以下で報告されている。
- Issue 182715: Data Binding & Espresso: IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation - Android Open Source Project - Issue Tracker - Google Project Hosting
- [Espresso test fails with java.lang.String cannot be cast to com.abc.events.databinding.SponsorDetailBinding](http://stackoverflow.com/questions/33890393/espresso-test-fails-with-java-lang-string-cannot-be-cast-to-com-abc-events-datab - Stack Overflow)
私は遭遇していないのだけれど、以下のようなエラーが出ることもある模様。
java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
at android.databinding.DataBindingUtil.<clinit>(DataBindingUtil.java:31)
at com.espresso.databinding.MainActivity.onCreate(MainActivity.java:15)
対応
上記ページに workaround が書かれていた。 どうやら Data Binding のためのタスクが androidTest
向けにも動いていて、それが原因でおかしくなってるぽい。
上記ページの workaround をもとに、以下のようなコードを build.gradle に書いてとりあえず回避した。
project.afterEvaluate {
def targetTasks = tasks.findAll({ it.name ==~ /\AdataBindingExportBuildInfo.*AndroidTest\z/ }).each {
it.deleteAllActions()
}
// 将来予期せず動作しなくなるなどしたときのために例外を投げる。
if (targetTasks.empty) throw new RuntimeException('対象となるタスクが存在しませんでした。 ' +
'Data binding と Espresso の組み合わせのための workaround が不要になった可能性があります。 ' +
'ビルドスクリプトを見直してください。')
}
dataBindingExportBuildInfoDebugAndroidTest
や dataBindingExportBuildInfoReleaseAndroidTest
といったタスクの処理を全部無くしてしまうというもの。
将来タスク名が変更されたりして workaround のコードが動かなくなったときに気付くように例外を投げるようにしておいた。