PendingIntent单元测试:如何为指定函数编写测试用例?
核心测试点
这段代码的核心是通过NavDeepLinkBuilder构建跳转至UserActivity的PendingIntent,并调用上下文启动它。我们需要验证以下几点:
NavDeepLinkBuilder的配置方法是否按预期调用- 上下文的
startIntentSender是否被正确触发 - 异常场景下的错误处理逻辑是否生效
依赖准备
确保测试依赖中包含Mockito(用于模拟Android框架类):
testImplementation "org.mockito:mockito-core:5.6.0" testImplementation "org.mockito:mockito-inline:5.6.0" // 用于mock静态方法和final类
测试用例示例
1. 测试正常流程:验证NavDeepLink配置与启动逻辑
假设你把目标代码封装到了YourClass.launchUserActivity(Context)方法中,测试代码如下:
import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import android.content.Context; import android.content.IntentSender; import android.app.PendingIntent; import androidx.navigation.NavDeepLinkBuilder; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class NavigationTest { @Mock private Context mockContext; @Mock private PendingIntent mockPendingIntent; @Mock private IntentSender mockIntentSender; @Test public void launchUserActivity_ShouldConfigureDeepLinkAndStartIntent() throws Exception { // 模拟NavDeepLinkBuilder的链式调用 try (var mockedBuilder = mockStatic(NavDeepLinkBuilder.class)) { NavDeepLinkBuilder mockBuilder = mock(NavDeepLinkBuilder.class); // 构造链式调用的返回值,保证调用链完整 mockedBuilder.when(() -> new NavDeepLinkBuilder(mockContext)).thenReturn(mockBuilder); when(mockBuilder.setGraph(eq(R.navigation.flow_nav_graph))).thenReturn(mockBuilder); when(mockBuilder.setDestination(eq(R.id.UserActicity))).thenReturn(mockBuilder); when(mockBuilder.setComponentName(eq(UserActivity.class))).thenReturn(mockBuilder); when(mockBuilder.createPendingIntent()).thenReturn(mockPendingIntent); // 模拟PendingIntent返回IntentSender when(mockPendingIntent.getIntentSender()).thenReturn(mockIntentSender); // 执行目标方法 YourClass.launchUserActivity(mockContext); // 验证NavDeepLinkBuilder的配置是否完全符合预期 mockedBuilder.verify(() -> new NavDeepLinkBuilder(mockContext)); verify(mockBuilder).setGraph(R.navigation.flow_nav_graph); verify(mockBuilder).setDestination(R.id.UserActicity); verify(mockBuilder).setComponentName(UserActivity.class); verify(mockBuilder).createPendingIntent(); // 验证上下文是否正确调用了startIntentSender,参数匹配 verify(mockContext).startIntentSender( eq(mockIntentSender), eq(null), eq(0), eq(0), eq(0) ); } } }
2. 测试异常场景:验证异常时的栈轨迹打印
@Test public void launchUserActivity_WhenStartIntentThrowsException_ShouldPrintStackTrace() throws Exception { try (var mockedBuilder = mockStatic(NavDeepLinkBuilder.class)) { NavDeepLinkBuilder mockBuilder = mock(NavDeepLinkBuilder.class); mockedBuilder.when(() -> new NavDeepLinkBuilder(mockContext)).thenReturn(mockBuilder); when(mockBuilder.setGraph(eq(R.navigation.flow_nav_graph))).thenReturn(mockBuilder); when(mockBuilder.setDestination(eq(R.id.UserActicity))).thenReturn(mockBuilder); when(mockBuilder.setComponentName(eq(UserActivity.class))).thenReturn(mockBuilder); when(mockBuilder.createPendingIntent()).thenReturn(mockPendingIntent); when(mockPendingIntent.getIntentSender()).thenReturn(mockIntentSender); // 模拟startIntentSender抛出异常 Exception testException = new Exception("Test exception"); doThrow(testException).when(mockContext).startIntentSender( eq(mockIntentSender), eq(null), eq(0), eq(0), eq(0) ); // 执行目标方法 YourClass.launchUserActivity(mockContext); // 验证异常的printStackTrace方法被调用 verify(testException).printStackTrace(); } }
测试说明
- 用
mockStatic模拟NavDeepLinkBuilder的构造方法,因为它是通过new实例化的 - 链式调用的模拟需要让每个配置方法返回mock的Builder实例,确保调用链不中断
- 异常场景中通过
doThrow模拟启动逻辑抛出异常,再验证错误处理逻辑是否生效
内容的提问来源于stack exchange,提问作者Chaitanya Aggarwal
相关产品推荐
相关产品推荐

