5月30日 23:22

Module Federation 应该怎么测试才不会漏线上问题?

Module Federation 的测试难点在于:你测到的代码,不一定就是线上组合后的代码。Remote 本地单测通过,Host 集成时可能因为共享依赖版本不一致、remoteEntry 缓存、运行时加载失败而出问题。所以测试策略不能只覆盖组件本身,还要覆盖契约、集成、降级和发布后的真实加载链路。

建议把测试分成四层。第一层是 Remote 内部单元测试,确保组件、Hook、工具函数按预期工作;第二层是契约测试,确保暴露模块的 Props、事件和类型没有破坏调用方;第三层是 Host 集成测试,验证真实 remoteEntry 能被加载并完成关键流程;第四层是端到端和发布后探测,确认 CDN、权限、环境变量、缓存策略都没问题。层级越往上越贵,所以不要把所有问题都交给 E2E,单测和契约测试要先挡住大部分低级错误。

ts
// contract.test.ts import type { OrderListProps } from '../src/pages/OrderList' test('OrderList contract keeps required props stable', () => { const props: OrderListProps = { userId: 'u_1', onSelect: () => undefined } expect(props.userId).toBeTruthy() })
ts
// playwright: host loads remote test('host can open order remote', async ({ page }) => { await page.goto('/orders') await expect(page.getByText('订单列表')).toBeVisible() await expect(page.locator('[data-remote="order"]')).toBeVisible() })

这两段代码分别挡住不同风险。契约测试不追求验证 UI,而是提醒你“这个暴露模块还是否符合调用方预期”;Playwright 测试则要尽量接近真实环境,加载构建后的 remoteEntry,而不是直接 import 本地源码。很多团队踩坑是 CI 里测的是源码,生产跑的是 CDN 文件,中间缺了一层最关键的组合验证。

追问

Remote 自己测过了,为什么 Host 还要测?

Remote 单测只能证明它在自己的环境里能跑,不能证明它和 Host 的共享依赖、路由上下文、权限上下文能正确配合。Host 测试关注的是组合结果,例如 remoteEntry 是否能加载、Suspense fallback 是否消失、错误边界是否兜住异常。取舍在于 Host 集成测试数量不能太多,否则 CI 会变慢。建议只覆盖登录后首屏、核心业务路径和每个 Remote 的入口页。

契约测试应该测什么,不应该测什么?

契约测试应该测暴露模块的公开接口,包括 Props、事件、返回类型、必要上下文和约定的 DOM 标识。它不应该测试内部实现,也不应该关心按钮用什么颜色、列表内部怎么分页。边界越清楚,Remote 团队越能自由重构。踩坑是把契约测试写成快照大集合,任何样式变化都让调用方 CI 失败,最后大家只会选择跳过测试。

共享依赖版本怎么在测试里发现问题?

可以在集成测试启动时打印并断言关键依赖版本,尤其是 React、React DOM、路由和状态库。更实用的做法是在测试环境使用和生产相同的构建产物,让 Module Federation 的 share scope 真正初始化。只在 Jest 里 require('react') 判断单例意义不大,因为它没有复现远程加载过程。版本问题通常表现为 Hook 调用异常、Context 丢失或样式组件主题失效,测试用例要覆盖这些症状。

E2E 测试要不要覆盖所有 Remote 页面?

不要。Module Federation 项目里 Remote 数量一多,全量 E2E 会慢到没人愿意等,也容易因为无关服务波动导致失败。更好的策略是每个 Remote 保留一条冒烟路径,关键业务再补 2 到 3 条高价值流程。取舍是覆盖率看起来没那么漂亮,但反馈速度和稳定性会更好。细节逻辑仍然交给 Remote 自己的单测和组件测试。

发布后还需要做什么测试?

需要做合成探测,也就是定时从线上访问 Host,并检查每个 Remote 的入口是否能加载。这个探测要覆盖 remoteEntry 404、跨域错误、初始化失败、白屏和核心文案缺失。很多问题只有 CDN 缓存、Nginx 头、灰度配置参与后才出现,CI 阶段不一定能发现。发布后探测不是替代测试,而是给独立部署加一层保险。

Module Federation 的测试重点是把“模块能跑”和“系统能组合起来跑”分开看。单测保证局部质量,契约测试保护边界,集成和线上探测保证真实运行链路,这样才不容易把问题留到用户浏览器里。

标签:Module Federation