日々精進

新しく学んだことを書き留めていきます

Robolectricでテスト実行時にassetsフォルダ・resourcesフォルダを複数設定する

こんなのよくやることだと思うのに、dirty hackな方法しか見つからなかった。。 もっとまっとうな方法はないんだろうか?

  • RobolectricTestRunnerのサブクラス(MyTestRunner)を作る。
    • MyTestRunnerに以下を実装してassets/resourcesフォルダを追加する

@Override
protected ResourceLoader createAppResourceLoader(final ResourceLoader systemResourceLoader, final AndroidManifest appManifest) {
    try {
        RoutingResourceLoader loader = (RoutingResourceLoader) super.createAppResourceLoader(systemResourceLoader, appManifest);
        Field field = RoutingResourceLoader.class.getDeclaredField("resourceLoaders");
        field.setAccessible(true);
        Map<String, ResourceLoader> resourceLoaders = (Map<String, ResourceLoader>) field.get(loader);
        OverlayResourceLoader overlayResourceLoader = (OverlayResourceLoader) resourceLoaders.get(appManifest.getPackageName());
        field = OverlayResourceLoader.class.getDeclaredField("subResourceLoaders");
        field.setAccessible(true);
        List<PackageResourceLoader> packageResourceLoaders = (List<PackageResourceLoader>) field.get(overlayResourceLoader);

        // ここを修正
        ResourcePath rpInjected = new ResourcePath(appManifest.getRClass(), appManifest.getPackageName(), Fs.fileFromPath("../app/src/main/res"), Fs.fileFromPath("../app/src/main/assets"));
        packageResourceLoaders.add(createResourceLoader(rpInjected));
        rpInjected = new ResourcePath(appManifest.getRClass(), appManifest.getPackageName(), Fs.fileFromPath("../app/src/test/res"), Fs.fileFromPath("../app/src/test/assets"));
        packageResourceLoaders.add(createResourceLoader(rpInjected));
        // ここを修正

        return loader;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
  • テストクラスに@RunWith(MyTestRunner.class)を付ける

この方法はRobolectricの内部実装に依存しているので、Robolectricのバージョンが上がったら動かなくなる可能性高いです。ご注意を。

参考: