Android插桩测试中如何覆盖资源文件?
免责声明:此问题与相关Stack Overflow问题及回答有关,但存在差异。
我希望在AndroidManifest.xml中指定网络安全配置资源:
<application [...] android:networkSecurityConfig="@xml/network_security_config">
常规构建时,从app/src/main/res/xml/network_security_config.xml(main目录)加载资源;而插桩测试构建时,我想让它从app/src/androidTest/res/xml/network_security_config.xml(androidTest目录)加载对应的资源。
配置文件内容示例(仅作参考):
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="false" /> </network-security-config>
但实际测试发现,androidTest目录下的资源被忽略了——只有把文件放在app/src/debug/res/xml/network_security_config.xml才能覆盖debug构建的资源,但这不是我想要的。我需要的是仅在插桩测试时覆盖该资源,请问有没有办法让Android构建插桩测试包时使用androidTest目录下的资源?
解决方法
Android插桩测试的androidTest资源默认不会覆盖主应用的资源,因为插桩测试是作为独立APK安装并依附主应用运行的,主应用的Manifest和资源优先级更高。要实现仅在插桩测试时替换网络安全配置,有以下几种可行方案:
1. 构建变体+清单合并
创建专门的测试构建变体,在对应目录放置测试用配置,让插桩测试使用该变体:
- 在
app/build.gradle中添加测试变体:
android { flavorDimensions "environment" productFlavors { prod {} test {} } buildTypes { debug {} release {} } }
- 将测试用的
network_security_config.xml放在app/src/testDebug/res/xml/目录下 - 运行插桩测试时指定变体:
./gradlew connectedTestDebugAndroidTest
2. 动态修改配置(推荐)
在插桩测试的初始化代码中,通过反射动态替换网络安全配置。比如在测试基类的@Before方法中执行:
@Before fun setupNetworkConfig() { val application = ApplicationProvider.getApplicationContext<Application>() val res = application.resources // 测试用配置文件名改为network_security_config_test.xml,放在androidTest/res/xml/ val testConfigId = res.getIdentifier("network_security_config_test", "xml", application.packageName) try { val appInfoField = Application::class.java.getDeclaredField("mApplicationInfo") appInfoField.isAccessible = true val appInfo = appInfoField.get(application) as ApplicationInfo appInfo.networkSecurityConfigRes = testConfigId } catch (e: Exception) { e.printStackTrace() } }
3. 清单占位符替换
在主Manifest中使用占位符,通过Gradle为插桩测试构建替换值:
- 主
AndroidManifest.xml修改:
<application [...] android:networkSecurityConfig="${networkSecurityConfig}">
- 在
app/build.gradle中配置占位符:
android { defaultConfig { manifestPlaceholders = [networkSecurityConfig: "@xml/network_security_config"] } androidTest { manifestPlaceholders = [networkSecurityConfig: "@xml/network_security_config_test"] } }
- 将测试用配置放在
androidTest/res/xml/network_security_config_test.xml
内容的提问来源于Stack Exchange,提问作者JonasVautherin

