SuperAPI AI 工具集

launching-fragments-with-fragmentscenario

测试与质量

查看项目

更新于 10-16 04:00

技能介绍

本技能用于在隔离环境中测试单个 Fragment,通过 FragmentScenario 将 Fragment 托管在内部的 EmptyFragmentActivity 中,从而在不启动完整宿主 Activity 的情况下测试 Fragment 的 onCreate、onViewCreated 与生命周期。

用途

当你需要单独测试一个 Fragment、需要驱动其生命周期状态变化、或需要为无默认构造函数的 Fragment 注入 FragmentFactory 时使用。若宿主是 Activity 而非 Fragment,或 Fragment 依赖真实导航栈(NavHostFragment),则不适合使用本技能。

主要能力

两个入口方法:launchFragmentInContainer<F>() 将 Fragment 添加到 android.R.id.content,视图会附加到窗口,具备完整生命周期;launchFragment<F>() 采用 containerViewId = 0,为 headless 模式,onCreateView 仍会执行但视图不附加到窗口。两者均支持 fragmentArgs、themeResId、factory 等参数。

使用方式

  1. 依赖配置:fragment-testing 放在 androidTestImplementation;fragment-testing-manifest 必须放在 debugImplementation(宿主测试为 testImplementation),放在 androidTestImplementation 不会合并清单,会抛出 ActivityNotFoundException: EmptyFragmentActivity。

  2. 需要读取参数时传入 fragmentArgs。

  3. 使用 AppCompat/Material 控件的 Fragment 必须通过 themeResId 覆盖为 AppCompat 主题,默认主题 FragmentScenarioEmptyFragmentActivityTheme 继承 android:Theme.WithActionBar,即平台 Holo 主题,否则会因 AppCompat 控件膨胀崩溃。

  4. 非默认构造函数的 Fragment 可注入 FragmentFactory,或使用内联 lambda 重载。工厂存于基于 EmptyFragmentActivity 的 ViewModelStore 的 FragmentFactoryHolderViewModel 中,可跨 recreate() 存活。

  5. 用 moveToState 驱动生命周期(STARTED/RESUMED/DESTROYED),用 onFragment 在主线程检查状态,用 withFragment 捕获带返回值的跨线程状态,用 recreate() 模拟配置变更。

  6. FragmentScenario 实现 Closeable,可用 use { } 包裹以确保测试失败时也会 close()。

限制与注意事项

不能传入 initialState = Lifecycle.State.DESTROYED,会被 IllegalArgumentException 拒绝,应先用 CREATED 启动再 moveToState(DESTROYED)。moveToState(DESTROYED) 或 close() 之后不可再调用 onFragment/withFragment,会抛 IllegalStateException。EmptyFragmentActivity 不安装 NavHostFragment,从其托管的 Fragment 调用 findNavController() 会抛 IllegalStateException,可改用 TestNavHostController 设置到 Fragment 视图上,或编写自定义测试宿主 Activity。此外,launchFragmentInContainer、launchFragment、moveToState 不可在主线程调用,否则会因 await 屏障死锁。

验证方式

检查 fragment-testing-manifest 是否配置在 debugImplementation(或 testImplementation);检查 AppCompat/Material Fragment 是否显式传入 themeResId;检查是否避免传入 initialState = DESTROYED;findNavController 相关测试是否在 moveToState(STARTED) 前安装 TestNavHostController;运行 connectedDebugAndroidTest 是否无相关异常。