You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Firebase Dynamic Link构建单元测试并实现链接唤起APP自动化测试

我之前也踩过这个坑——真机上通过邮件打开Firebase动态链接完全正常,但在自动化测试里死活触发不了App唤起,折腾了好一阵才捋清楚问题所在。下面分享我总结的单元测试写法,以及解决自动化测试中唤起问题的具体方案:

一、单元测试:聚焦动态链接解析逻辑

单元测试的核心是验证你的代码对动态链接的解析逻辑是否正确,而非测试系统级的App唤起(这属于UI自动化范畴)。毕竟单元测试跑在本地JVM,没有Android系统的Intent分发环境。

这里用Mockito来Mock Firebase的依赖,避免依赖真实SDK:

// 先添加测试依赖
testImplementation 'org.mockito:mockito-core:4.8.1'
testImplementation 'com.google.firebase:firebase-dynamic-links-testing:21.0.0'

@RunWith(MockitoJUnitRunner::class)
class DynamicLinkParserTest {

    @Mock
    private lateinit var mockFirebaseDynamicLinks: FirebaseDynamicLinks

    @Before
    fun setup() {
        // 让FirebaseDynamicLinks.getInstance()返回我们的Mock实例
        `when`(FirebaseDynamicLinks.getInstance()).thenReturn(mockFirebaseDynamicLinks)
    }

    @Test
    fun `parse valid dynamic link returns correct deep link`() {
        // 构造模拟的动态链接数据
        val expectedDeepLink = Uri.parse("myapp://product/123")
        val mockPendingLink = mock(PendingDynamicLinkData::class.java)
        `when`(mockPendingLink.link).thenReturn(expectedDeepLink)
        `when`(mockFirebaseDynamicLinks.getDynamicLink(any())).thenReturn(Task.forResult(mockPendingLink))

        // 调用你的解析方法
        val result = DynamicLinkParser.parse(mock(Intent::class.java))

        // 验证解析结果符合预期
        assertEquals(expectedDeepLink, result)
    }

    @Test
    fun `parse invalid dynamic link returns null`() {
        `when`(mockFirebaseDynamicLinks.getDynamicLink(any())).thenReturn(Task.forResult(null))

        val result = DynamicLinkParser.parse(mock(Intent::class.java))

        assertNull(result)
    }
}
二、自动化测试:解决App唤起失败的问题

测试中直接加载URL无法唤起App,本质是因为测试进程和系统Intent分发是隔离的,不会触发系统的App关联规则。我们需要分两种场景处理:

场景1:仅测试App内的链接处理逻辑

如果只需要验证App接收到动态链接后的页面跳转,无需模拟外部App唤起,可以直接构造对应的Intent传入:

@RunWith(AndroidJUnit4::class)
class DynamicLinkNavigationTest {

    @Rule
    @JvmField
    val activityRule = ActivityScenarioRule(MainActivity::class.java)

    @Test
    fun `dynamic link triggers product detail page`() {
        // 构造包含深层链接的Intent
        val deepLinkIntent = Intent(Intent.ACTION_VIEW, Uri.parse("myapp://product/123"))
            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

        // 给当前Activity传入这个Intent
        activityRule.scenario.onActivity { activity ->
            activity.startActivity(deepLinkIntent)
        }

        // 用Espresso验证页面跳转结果
        onView(withId(R.id.product_detail_title))
            .check(matches(isDisplayed()))
            .check(matches(withText("Product #123")))
    }
}

场景2:端到端测试完整唤起流程(从外部App到你的App)

如果需要完整模拟“从浏览器/邮件打开链接唤起App”的流程,必须用UI Automator操作系统级UI:

@RunWith(AndroidJUnit4::class)
class DynamicLinkEndToEndTest {

    private lateinit var uiDevice: UiDevice

    @Before
    fun setup() {
        uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
        // 回到主屏幕,准备测试
        uiDevice.pressHome()
        val launcherPackage = uiDevice.launcherPackageName
        assertNotNull(launcherPackage)
        uiDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), 5000)
    }

    @Test
    fun `open dynamic link in chrome launches app`() {
        // 启动Chrome并加载你的动态链接
        val chromeIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://your-dynamic-link.page.link/abc123"))
            .setPackage("com.android.chrome")
            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        InstrumentationRegistry.getInstrumentation().context.startActivity(chromeIntent)

        // 等待Chrome加载完成
        uiDevice.wait(Until.hasObject(By.pkg("com.android.chrome")), 5000)

        // 点击系统弹出的"打开应用"对话框按钮(部分设备是英文"Open",需根据测试环境调整)
        val openAppBtn = uiDevice.findObject(By.text("打开"))
        if (openAppBtn.exists()) openAppBtn.click()

        // 验证你的App被唤起并跳转到目标页面
        uiDevice.wait(Until.hasObject(By.pkg("com.your.app.package")), 5000)
        onView(withId(R.id.product_detail_title))
            .check(matches(isDisplayed()))
    }
}
三、额外排查点

如果还是不行,检查这几个常见坑:

  • 确保测试设备/模拟器上已正确配置App关联(assetlinks.json已上传到域名根目录,Firebase控制台已配置对应链接)
  • 检查AndroidManifest.xml里的Intent过滤器是否正确匹配动态链接域名:
<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data
        android:host="your-dynamic-link.page.link"
        android:scheme="https" />
</intent-filter>
  • 模拟器上可能需要禁用Chrome的“直接打开链接”选项,确保弹出“打开应用”的选择框

内容的提问来源于stack exchange,提问作者MiguelSlv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:57:09