Using multiple res folders with Robolectric

旧巷老猫 提交于 2019-12-17 17:13:42

问题


My current Gradle configuration has multiple (Merged) res folders:

sourceSets {
    androidTest {
        setRoot('src/test')
    }
    main {
        res.srcDirs =
            [
                'src/main/res/features/registration',
                'src/main/res/features/login',
                'src/main/res'
            ]
    }
}

But Robolectric allows me to configure a single directory using AndroidManifest:

public class RobolectricGradleTestRunner extends RobolectricTestRunner {
    private static final int MAX_SDK_SUPPORTED_BY_ROBOLECTRIC = 18;

    public RobolectricGradleTestRunner(Class<?> testClass) throws InitializationError {
        super(testClass);
    }

    @Override
    protected AndroidManifest getAppManifest(Config config) {
        String manifestProperty = "../app/src/main/AndroidManifest.xml";
        String resProperty = "../app/src/main/res";

        return new AndroidManifest(Fs.fileFromPath(manifestProperty), Fs.fileFromPath(resProperty)) {
            @Override
            public int getTargetSdkVersion() {
                return MAX_SDK_SUPPORTED_BY_ROBOLECTRIC;
            }
        };
    }
}

This way tests are failing. Is it possible to configure robolectric to reflect my gradle file?


回答1:


Another solution similar to Luca's:

public class MyTestRunner extends RobolectricTestRunner {
    ...
    @Override
    protected AndroidManifest getAppManifest(Config config) {
        String appRoot = "./src/main/";
        String manifestPath = appRoot + "AndroidManifest.xml";
        String resDir = appRoot + "res";
        String assetsDir = appRoot + "assets";

        return new AndroidManifest(Fs.fileFromPath(manifestPath), Fs.fileFromPath(resDir), Fs.fileFromPath(assetsDir)) {
            @Override
            public List<ResourcePath> getIncludedResourcePaths() {
                List<ResourcePath> paths = super.getIncludedResourcePaths();
                paths.add(new ResourcePath(getRClass(), getPackageName(), Fs.fileFromPath("../app/src/main/res/features/registration"), getAssetsDirectory()));
                paths.add(new ResourcePath(getRClass(), getPackageName(), Fs.fileFromPath("../app/src/main/res/features/login"), getAssetsDirectory()));
                return paths;
            }
        };
    }
}

Don't forget to annotate your tests with @RunWith(MyTestRunner.class)




回答2:


Ok, this is the easiest way to do it, You will have to extend RobolectricTestRunner getAppManifest and createAppResourceLoader.

In getAppManifest you will simply have to store the manifest in a field, let's say mDefaultManifest.

In createAppResourceLoader you will have to add the right resources injected.

/**
 * TODO: Watch OUT this is copied from RobolectricTestRunner in Robolectric-2.4 keep it up to date!
 */
@Override
protected ResourceLoader createAppResourceLoader(ResourceLoader systemResourceLoader, AndroidManifest appManifest) {
    List<PackageResourceLoader> appAndLibraryResourceLoaders = new ArrayList<PackageResourceLoader>();
    for (ResourcePath resourcePath : appManifest.getIncludedResourcePaths()) {
        appAndLibraryResourceLoaders.add(createResourceLoader(resourcePath));
    }

        /* BEGIN EDIT */
        if(mDefaultManifest != null) {
            ResourcePath rpInjected = new ResourcePath(mDefaultManifest.getRClass(), mDefaultManifest.getPackageName(), Fs.fileFromPath("../app/src/main/res/features/registration"), mDefaultManifest.getAssetsDirectory());
            appAndLibraryResourceLoaders.add(createResourceLoader(rpInjected));
            rpInjected = new ResourcePath(mDefaultManifest.getRClass(), mDefaultManifest.getPackageName(), Fs.fileFromPath("../app/src/main/res/features/login"), mDefaultManifest.getAssetsDirectory());
            appAndLibraryResourceLoaders.add(createResourceLoader(rpInjected));
        }
        /* END EDIT */

    OverlayResourceLoader overlayResourceLoader = new OverlayResourceLoader(appManifest.getPackageName(), appAndLibraryResourceLoaders);

    Map<String, ResourceLoader> resourceLoaders = new HashMap<String, ResourceLoader>();
    resourceLoaders.put("android", systemResourceLoader);
    resourceLoaders.put(appManifest.getPackageName(), overlayResourceLoader);
    return new RoutingResourceLoader(resourceLoaders);
}

Do not forget to add @RunWith(YourTestRunner.class) in your test classes.



来源:https://stackoverflow.com/questions/27618660/using-multiple-res-folders-with-robolectric

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!