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

React Testing Library+AWS Amplify测试路由回退跳转异常问题

问题根因

该问题由三处测试逻辑错误共同导致,和Cognito Mock本身无关:

  • 测试组件树和生产环境不一致:你直接单独渲染<AddTimeSeriesFiles />单组件,没有挂载<Switch>路由匹配规则、UserContext.Provider等上层依赖,PrivateRoute路由守卫读不到合法认证状态,自动触发重定向逻辑把路径打到/根路由。同时因为Page A组件被直接挂在Router下,不受Switch的路由匹配规则约束,所以DOM会一直显示Page A内容,才会出现路径和渲染内容不匹配的异常。
  • 路由历史栈初始化错误:你调用history.push('', {})时直接把初始路径设为根路径/,也没有提前在历史栈中存入Page B的访问记录。页面返回按钮本质是调用history.goBack(),历史栈里没有Page B的条目,自然无法跳回目标地址。
  • 异步逻辑未等待:Mock的Auth.currentAuthenticatedUser是异步返回,点击返回按钮后认证校验、路由跳转的逻辑还没执行完成就同步做断言,拿不到最终的路由状态。
修复方案

按以下顺序调整测试代码即可:

  1. 修正Memory History初始化逻辑,模拟真实的用户访问历史栈,初始路径直接指向Page A,栈底保留Page B的访问记录:
    // 历史栈顺序和真实流程一致:先访问Page B,再跳转到Page A
    const history = createMemoryHistory({
      initialEntries: ['/add-station-options', '/add-time-series-files'],
      initialIndex: 1 // 默认停在Page A
    });
    
  2. 补全测试环境的组件树,和App.tsx里的生产结构保持一致,不要单独渲染单个页面组件,同时Mock UserContext的传值,保证路由守卫能读到已认证状态:
    // 提前Mock UserContext需要的值,isLoadingUser必须设为false
    const mockUserCtx = {
      user: { attributes: {} },
      isLoadingUser: false,
      handleSignIn: jest.fn(),
      handleSignOut: jest.fn(),
      handleUpdateAttributes: jest.fn(),
      handleConfirmEmailChange: jest.fn(),
      handleChangePassword: jest.fn(),
    };
    
    render(
      <MockTheme>
        <Router history={history}>
          <UserContext.Provider value={mockUserCtx}>
            <ErrorProvider>
              <SuccessProvider>
                <AddStationProvider>
                  <Switch>
                    <PrivateRoute exact path={urls.addTimeSeriesFiles}>
                      <AddTimeSeriesFiles />
                    </PrivateRoute>
                    <PrivateRoute exact path={urls.addStationOptions}>
                      <AddStationOptions />
                    </PrivateRoute>
                    <PrivateRoute exact path={urls.addStationInfo}>
                      <AddStationInfoPage />
                    </PrivateRoute>
                    <Route exact path="/">
                      <div>Root Page</div>
                    </Route>
                  </Switch>
                </AddStationProvider>
              </SuccessProvider>
            </ErrorProvider>
          </UserContext.Provider>
        </Router>
      </MockTheme>
    );
    
  3. 点击返回按钮后,等待异步路由跳转完成再做断言,优先通过DOM元素判断页面是否跳转,再校验路径值,避免异步时序问题导致假失败:
    fireEvent.click(screen.getByRole('button', { name: /Back/ }));
    // 等待Page B的标志性元素渲染完成,证明跳转成功
    await waitFor(() => {
      expect(screen.getByText(/Add Station Options页面的固定文本/)).toBeInTheDocument();
    });
    expect(history.location.pathname).toBe('/add-station-options');
    
优化建议
  • 涉及路由跳转的测试不要单独渲染单个页面组件,一定要渲染完整的路由配置和上层依赖Provider,否则路由守卫、路由匹配逻辑都不会按预期工作。
  • 路由跳转是异步行为,所有点击后的断言都要放在waitFor里等待状态更新完成,不要同步执行断言。
  • 如果PrivateRoute是直接调用Auth.currentAuthenticatedUser做校验而非读取UserContext,需要在渲染组件后先等待认证校验完成,再操作页面元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:54:12