UI测试中无法授予ACCESS_NOTIFICATION_POLICY权限的问题问询
解决Android UI测试中授予ACCESS_NOTIFICATION_POLICY权限的问题
因为ACCESS_NOTIFICATION_POLICY属于特殊权限,不在常规运行时权限范围内,所以无法通过uiAutomation.grantRuntimePermission直接授予,且RuntimePermissionsStubber在espresso-intents 3.6.1版本中已被移除,以下是两种可行的解决办法:
方法一:用UiAutomator模拟手动授予权限
特殊权限需要用户在系统设置中手动开启,UI测试中可以通过UiAutomator模拟跳转设置页面并操作授权的流程:
- 在应用中添加权限跳转逻辑(测试时触发):
// 当权限未授予时,跳转到设置页面 if (!PermissionUtils.isNotificationPolicyAccessGranted(context)) { Intent intent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); }
- 在测试用例中用UiAutomator完成授权操作:
@RunWith(AndroidJUnit4.class) public class PermissionTest { @Test public void testNotificationPolicyPermission() { Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); // 启动应用并触发权限检查逻辑 Intent appIntent = targetContext.getPackageManager().getLaunchIntentForPackage(targetContext.getPackageName()); appIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); InstrumentationRegistry.getInstrumentation().startActivitySync(appIntent); // 跳转到权限设置页面(如果应用未自动跳转,可手动启动Intent) Intent settingsIntent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); targetContext.startActivity(settingsIntent); // 使用UiAutomator操作授权 UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); // 根据设备上的实际文本调整,比如"允许"或"允许修改通知策略" UiObject allowOption = device.findObject(new UiSelector().textContains("允许")); if (allowOption.exists() && allowOption.isEnabled()) { allowOption.click(); } // 返回应用继续测试 device.pressBack(); } }
注意:不同设备/系统版本的设置页面文本可能不同,需要根据测试环境调整UiSelector的匹配条件。
方法二:Mock权限检查结果(无需实际授权)
如果测试的核心是验证权限授予后的业务逻辑,而非权限申请流程,可以通过Mock权限检查方法来绕过真实的权限校验:
- 先将权限检查逻辑封装到工具类中:
public class PermissionHelper { public boolean isNotificationPolicyAccessGranted(Context context) { NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); return nm != null && nm.isNotificationPolicyAccessGranted(); } }
- 在测试中使用Mockito Mock该工具类的返回值:
@RunWith(AndroidJUnit4.class) public class BusinessLogicTest { @Mock PermissionHelper mockPermissionHelper; @Before public void setUp() { MockitoAnnotations.openMocks(this); // 让权限检查始终返回已授予 when(mockPermissionHelper.isNotificationPolicyAccessGranted(any(Context.class))).thenReturn(true); // 如果应用中是通过依赖注入获取PermissionHelper,直接替换为mock实例;如果是静态方法,可使用PowerMock进行静态Mock } @Test public void testLogicWithPermissionGranted() { // 执行需要权限的业务逻辑测试,此时会认为权限已授予 } }
如果是静态方法且无法修改应用代码,可使用PowerMock配合Mockito实现静态Mock,但需要注意PowerMock与AndroidX Test的兼容性。
内容的提问来源于stack exchange,提问作者cambunctious
相关产品推荐
相关产品推荐

