Android单元测试利器–Robolectric asset资源加载demo

2016/07/11

本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接

Android asset资源加载demo

先前有提到,本地单元测试里可以配置AndroidManifest, assests等目录,然而并没有什么卵用,读取的AndroidManifest还是主模块的AndroidManifest和assets,要想使用特殊的assets或者AndroidManifest必须自己写TestRunner,本节就讲解如何加载自定义的AndroidManifest和assets资源。

Android单元测试系列文章的代码都可以在Github上找到: https://github.com/cloudchou/RobolectricDemo

首先实现一个自定义的从RobolectricGradleTestRunner集成的TestRunner:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//可以修改AndroidManifest和asset的TestRunner
public class RobolectricGradleTestRunner2 extends RobolectricGradleTestRunner {

    public RobolectricGradleTestRunner2(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected AndroidManifest getAppManifest(final Config config) {
        //使用父类的方法创建AndroidManifest对象,
        //因为我们只修改AndroidManifest对象的AndroidManifest文件的位置
        // 和assets文件夹的位置
        AndroidManifest appManifest = super.getAppManifest(config);
        //只有当我们在测试脚本里设置了manifest时,自定义TestRunner才处理
        if (config.manifest() != null && !"".equals(config.manifest())) {
            //使用反射修改AndroidManifest对象的androidManifestFile字段的值,
            //使其指向我们设置的AndroidManifest文件的位置
            FileFsFile manifestFile = FileFsFile.from(config.manifest());
            Class<? extends AndroidManifest> appManifestClass = null;
            try {
                appManifestClass = appManifest.getClass();
                Field androidManifestFileField;
                try {
                    androidManifestFileField = appManifestClass.getDeclaredField("androidManifestFile");
                } catch (NoSuchFieldException e) {
                    androidManifestFileField = appManifestClass.getSuperclass().getDeclaredField("androidManifestFile");
                }
                androidManifestFileField.setAccessible(true);
                androidManifestFileField.set(appManifest, manifestFile);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            //使用反射修改AndroidManifest对象的assetsDirectory字段的值,
            //使其指向我们设置的assets文件夹的位置
            String parent = new File(config.manifest()).getParent();
            FileFsFile assetFile = FileFsFile.from(parent, config.assetDir());
            try {
                Field assetsDirectoryField = appManifestClass.getDeclaredField("assetsDirectory");
                assetsDirectoryField.setAccessible(true);
                assetsDirectoryField.set(appManifest, assetFile);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return appManifest;
    }

}

然后再看如何在测试脚本里设置manifest进行测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//必须指定使用自定义的TestRunner才能指定AndroidManifest文件的位置进行加载
@RunWith(RobolectricGradleTestRunner2.class)
@Config(constants = BuildConfig.class, sdk = 21)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
public class ManifestConfigTest {

    //指定使用test目录下的AndroidManifest.xml 这时asse
    @Test
    @Config(manifest = "src/test/AndroidManifest.xml")
    public void testManifestConfig() throws PackageManager.NameNotFoundException, IOException {
        String packageName = RuntimeEnvironment.application.getPackageName();
        PackageManager packageManager = RuntimeEnvironment.application.getPackageManager();
        PackageInfo packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
        System.out.println(packageInfo.activities);
        System.out.println(packageName);
        System.out.println(packageInfo.versionCode);
        System.out.println(packageInfo.versionName);
        //从assets目录下加载test.prop文件
        InputStream fileInputStream = RuntimeEnvironment.application.getAssets().open("test.prop");
        Properties props = new Properties();
        props.load(fileInputStream);
        String property = props.getProperty("ro.product.cpu.abilist");
        System.out.println(property);
    }
}

代码结构如下所示:

manifest_test

执行结果如下所示:

manifest_test_result

¥打赏5毛

取消

感谢您的支持,我会继续努力的!

扫码支持
赏个5毛,支持我把

打开支付宝扫一扫,即可进行扫码打赏哦

本篇目录