※ 2015/06/28 20:31追記 ART環境だったら動きました。4.4系でもRuntimeをARTにしておけばテスト動きます
問題
Data Binding + Multidex倒したら「クックック奴と倒すとはな...さあやろうか」って感じで新たな問題が出てきました。テストコード側でBindingクラスに触ると死ぬ。
— 八木 (@sys1yagi) 2015, 6月 17
具体的にはこんなコードです。
@Test public void test() { //XXXBindingはData Bindingで生成したクラスです XXXBinding binding = XXXBinding.inflate(LayoutInflater.from( InstrumentationRegistry.getTargetContext() )); assertThat(binding, is(notNullValue())); }
ActivityMvvmBinding.inflate()
の所で以下のエラーが出ます。
java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
原因?
ClassLoaderの関係で問題が起きているようです。テストコードをビルドするとテストプロジェクト側でもData Binding用のクラスが生成されます。これによりテスト側のXXXBindingとアプリケーション側のXXXBindingが異なりエラーが起こっているようです。が正確にはわかりません。
対応
issue trackerに以下の投稿がありました。
その中で「環境の問題だったわー」という会話がされています。投稿者のSample CodeにはTest could not run Below android 5.0 !!
という文言が更新されてました。
Android5.0以上で実行しなければならないようですね!!!早速エミュレータを使って実行してみます。次はこんなエラーが。
java.lang.IllegalStateException: DataBinding must be created in view's UI Thread
なるほどUIスレッドじゃないとダメなようです。これはもう簡単ですね。最終的に以下のコードとなりました。
@Test public void test() { InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { ActivityMvvmBinding binding = ActivityMvvmBinding.inflate(LayoutInflater.from( InstrumentationRegistry.getTargetContext() )); assertThat(binding, is(notNullValue())); } }); }
まとめ
- Data Bindingを使ったテストはAndroid5.0以上の環境で実行するべし(※ 2015/06/28 20:31追記 ART環境だったら動きました。4.4系でもRuntimeをARTにしておけばテスト動きます)
- XXXBindingはUI Threadで触る必要がある。
Instrumentation#runOnMainSync(Runnable)
などを使おう - XXXBindingのテストを書くとActivityとか無しでActivityの状態変化のテストができて便利ですね?