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

如何监视并测试Promise被拒绝时catch块内的调用函数?

测试React组件中Promise拒绝时catch块的函数调用

嘿,我来帮你搞定这个测试需求!要验证当resetPassword()返回的Promise被拒绝时,displayErrorAlert是否在catch块里被正确调用,用Jest的函数间谍(spy)就能轻松实现,下面我给你详细的步骤和代码示例~

核心思路

我们需要完成这几件关键事:

  • 模拟resetPassword函数,让它返回一个被拒绝的Promise,模拟接口失败的场景
  • 创建displayErrorAlert的间谍,用来追踪它是否被调用以及调用参数
  • 模拟组件的表单提交,触发handleSubmit方法
  • 等待异步代码执行完毕后,断言间谍是否被正确调用

用React Testing Library实现的测试代码

React Testing Library是现在React官方推荐的测试工具,写法更贴近用户真实操作:

import { render, screen, fireEvent } from '@testing-library/react';
import ResetPassword from './ResetPassword';

describe('ResetPassword Component', () => {
  it('calls displayErrorAlert when resetPassword Promise is rejected', async () => {
    // 1. 创建所有需要的模拟函数/间谍
    const mockResetPassword = jest.fn().mockRejectedValue({ error: '模拟错误' });
    const mockDisplayErrorAlert = jest.fn();
    const mockHistory = { push: jest.fn() };

    // 2. 渲染组件,传入模拟的props
    render(
      <ResetPassword
        resetPassword={mockResetPassword}
        displayErrorAlert={mockDisplayErrorAlert}
        history={mockHistory}
      />
    );

    // 3. 找到表单并模拟提交(记得给组件里的表单加data-testid="reset-password-form"哦)
    const formElement = screen.getByTestId('reset-password-form');
    fireEvent.submit(formElement);

    // 4. 等待Promise的异步处理完成
    await Promise.resolve();

    // 5. 断言displayErrorAlert被正确调用
    expect(mockDisplayErrorAlert).toHaveBeenCalledWith(
      'impossible to change password. You should ask for a new reset password link',
      6000
    );

    // 额外验证:因为Promise被拒绝,then块里的history.push不会被触发
    expect(mockHistory.push).not.toHaveBeenCalled();
  });
});

用Enzyme实现的测试代码(如果你还在使用Enzyme)

如果你习惯用Enzyme,写法也类似:

import { shallow } from 'enzyme';
import ResetPassword from './ResetPassword';

describe('ResetPassword Component', () => {
  it('triggers displayErrorAlert when resetPassword fails', async () => {
    // 创建模拟函数
    const mockResetPassword = jest.fn().mockRejectedValue({ error: '测试错误' });
    const mockDisplayErrorAlert = jest.fn();
    const mockHistory = { push: jest.fn() };

    // 浅渲染组件
    const wrapper = shallow(
      <ResetPassword
        resetPassword={mockResetPassword}
        displayErrorAlert={mockDisplayErrorAlert}
        history={mockHistory}
      />
    );

    // 模拟表单提交,直接触发handleSubmit
    wrapper.find('form').simulate('submit', { preventDefault: () => {} });

    // 等待异步代码执行
    await Promise.resolve();

    // 断言函数调用
    expect(mockDisplayErrorAlert).toHaveBeenCalledWith(
      'impossible to change password. You should ask for a new reset password link',
      6000
    );
    expect(mockHistory.push).not.toHaveBeenCalled();
  });
});

关键细节说明

  • mockRejectedValue({ error: 'xxx' }):专门用来模拟Promise被拒绝的情况,和你组件里catch块接收{ error }的结构保持一致
  • await Promise.resolve():因为Promise的处理是异步的,我们需要等待事件循环走完,确保catch块里的代码完全执行完毕后再做断言
  • 断言调用参数完全匹配:确保displayErrorAlert接收的提示文本和时长都是你预期的内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:05:46