公式のやることリスト
公式が Wiki にガイドを用意してくれています。基本的にはこのガイドに従ってアップデートしていきます。
足りない部分
しかしアプリケーションによっては足りない部分があり、テストがテストケースとは関係ない部分でバッタバッタと死んでいく事があります。
1. targetSdk が 22 で落ちる
現状 Robolectric 3.0 で対応しているのは 21 までです。targetSdkVersion を 22 にしていると、UnsupportedOperationException
でテストができません。
対応するには、@Config
アノテーションでバージョンを指定します。
@Config(constants = BuildConfig.class, sdk = 21)
public class SomeTest {}
2. MultiDex で落ちる
Multidex を使っているプロジェクトでは、MultidexApplication
を継承したApplication
クラスを用意するか、MultidexApplication
をそのまま使用するか、どちらかをすることになりますが、attachBaseContext()
内でのMultidex#install()
はテストからはうまく実行できず例外で落ちます。
テストでは Multidex は関係ないので、例外を吐こうが影響はないですから、例外をキャッチするようにします。サポートライブラリのMultidexApplication
を使用している場合、そちらのコードを丸パクリして try-catch 句を追記したクラスを自分で用意します。
public class MultidexApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
try { // avoid robolectric error
MultiDex.install(this);
} catch (RuntimeException ignored) {
// ok to ignore exception while testing
}
}
}
3. AndroidManifest やその他のリソースが見つからなくて落ちる
ApplicationId をビルドスクリプトで指定していて、それが実際のパッケージ構成と違う場合に起きるものです。すべてのテストで Resources$NotFoundException が出てきて、謎のリソースを参照しようとして無いと怒られるようなパターンはこれです。
パッケージ名を指定する設定が@Config
アノテーションにはありますが、そうするとこんどは ResourceLoader が見つからないという理由でテストがクラッシュします。
さくっと解決するならば、以下のようなTestRunner
を用意してしまうことでテストが動くようになります。
public class MyTestRunner extends RobolectricGradleTestRunner {
public MyTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
}
@Override
protected AndroidManifest getAppManifest(Config config) {
return new AndroidManifest(
Fs.fileFromPath("../DriveMode/src/main/AndroidManifest.xml"),
Fs.fileFromPath("../DriveMode/build/intermediates/res/" + BuildConfig.FLAVOR + "/debug"),
Fs.fileFromPath("../DriveMode/build/intermediates/assets/" + BuildConfig.FLAVOR + "/debug/"));
}
}
すべてのテストで以下のように@RunWith
を指定すれば完了です。
@Config(constants = BuildConfig.class, sdk = 21)
@RunWith(MyTestRunner.class)
public class SomeTest {}
これで、すべてのテストが一律同じ理由でバッタバッタと死んでいく現象は解消されます。