Android 3.1:请求拨打电话权限类的单元测试实现疑问
嘿,我之前在做MVP架构的Android应用时,也碰到过类似的权限请求单元测试问题,刚好能给你捋清楚思路和具体做法!
你的权限请求逻辑在Presenter里,而Presenter肯定依赖了Android的系统API(比如Context.checkSelfPermission()或者请求权限的方法)。单元测试的关键是脱离Android环境,用Mock框架模拟这些系统依赖,这样就能专注验证Presenter的逻辑是否正确触发了权限请求,不用启动模拟器或真机。
1. 准备Mock工具
首先确保项目里引入了JUnit和Mockito(最常用的Android单元测试Mock框架),在你的build.gradle(Module级)里添加依赖:
testImplementation 'junit:junit:4.13.2' testImplementation 'org.mockito:mockito-core:4.5.1'
2. 模拟Presenter的依赖
假设你的Presenter依赖两个东西:一个是和View交互的接口(比如CallView,用来触发权限请求或发起呼叫),另一个是Context(用来检查权限)。我们用Mockito来Mock这两个依赖:
@RunWith(MockitoJUnitRunner.class) public class CallPresenterTest { // Mock Context对象 @Mock private Context mockContext; // Mock View接口 @Mock private CallView mockView; // 待测试的Presenter实例 private CallPresenter presenter; @Before public void setup() { // 初始化Presenter,传入Mock的依赖 presenter = new CallPresenter(mockContext, mockView); } }
3. 测试核心逻辑:权限请求触发
分两种场景测试,覆盖所有情况:
场景1:权限未授予时,Presenter应触发权限请求
我们先模拟系统返回权限未授予的结果,然后触发Presenter的拨打电话方法,验证它是否正确调用了View的权限请求方法:
@Test public void whenCallButtonClicked_PermissionDenied_ShouldRequestPermission() { // 模拟Context检查权限的结果:未授予 when(mockContext.checkSelfPermission(Manifest.permission.CALL_PHONE)) .thenReturn(PackageManager.PERMISSION_DENIED); // 触发用户点击按钮的逻辑 presenter.onCallButtonClicked(); // 验证Presenter是否通知View发起权限请求 verify(mockView).requestCallPhonePermission(); }
场景2:权限已授予时,Presenter应直接发起呼叫
模拟权限已授予的情况,验证Presenter是否直接触发拨打电话的逻辑:
@Test public void whenCallButtonClicked_PermissionGranted_ShouldStartCall() { when(mockContext.checkSelfPermission(Manifest.permission.CALL_PHONE)) .thenReturn(PackageManager.PERMISSION_GRANTED); presenter.onCallButtonClicked(); // 验证Presenter是否通知View发起电话呼叫 verify(mockView).startPhoneCall(); }
4. 测试权限请求的回调逻辑
如果你的Presenter还要处理权限请求后的结果(比如用户允许/拒绝权限),也需要测试这部分:
@Test public void onPermissionGranted_ShouldInitiateCall() { // 模拟权限请求成功的回调 presenter.onPermissionResult(Manifest.permission.CALL_PHONE, PackageManager.PERMISSION_GRANTED); verify(mockView).startPhoneCall(); } @Test public void onPermissionDenied_ShouldShowError() { // 模拟权限请求被拒绝的回调 presenter.onPermissionResult(Manifest.permission.CALL_PHONE, PackageManager.PERMISSION_DENIED); verify(mockView).showPermissionDeniedMessage(); }
你说的那个Stack Overflow问题里提到的Espresso,属于UI集成测试,是用来验证整个流程(从按钮点击到系统权限弹窗出现)的表现;而我们上面做的是单元测试,专注于Presenter的逻辑正确性,运行在本地JVM上,速度快,能快速验证逻辑是否正确。两者可以配合使用,单元测试保证逻辑正确,Espresso测试保证UI流程正常。
为了让Presenter更易测试,建议把权限相关的操作封装到一个单独的PermissionHelper类里(比如封装checkPermission、requestPermission方法),这样Mock起来更灵活,也符合单一职责原则,避免Presenter直接依赖Android系统API。
内容的提问来源于stack exchange,提问作者Val

