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

React项目Cypress组件测试:如何用Spy替代Jest.fn()断言点击事件

Cypress组件测试:用Spy替代Jest Mock断言点击处理器

我在React项目中尝试Cypress组件测试,对点击处理器的断言操作存在困惑。之前用Jest时可以这样实现:

const hideMock = jest.fn();

renderWithProviders(
    <EmployeeCreationWizard
        hide={hideMock}
        isVisible={true}
        employeeId={123}
    />,
);

await cancel();

expect(hideMock).toBeCalledTimes(1);

如何用Cypress Spy实现类似const hideMock = jest.fn();的功能?

以下是我目前的代码:

it.only('invoke hide() once upon clicking on cancel button', () => {
    const hideSpy = cy.spy();
    cy.interceptEmployeeCreationWizard();
    cy.mount(
      <EmployeeCreationWizard
        isVisible={true}
        hide={hideSpy}
        employeeId={123}
      />,
    );

    cy.findByTestId('employee-wizard-drawer-cancel').click();
    cy.get('[data-test-id="employee-wizard-drawer-close"]').click();
    // eslint-disable-next-line @typescript-eslint/no-unused-expressions
    // expect(hideSpy).to.be.calledOnce;
  });

解决方案

Cypress的cy.spy()和Jest的jest.fn()功能类似,但需要结合Cypress的异步断言机制来使用,不能直接用同步的expect断言。你可以通过以下两种方式实现正确的断言:

方式1:通过变量结合cy.wrap()断言

it.only('点击取消按钮时调用hide()一次', () => {
  const hideSpy = cy.spy();

  cy.interceptEmployeeCreationWizard();
  cy.mount(
    <EmployeeCreationWizard
      isVisible={true}
      hide={hideSpy}
      employeeId={123}
    />,
  );

  cy.findByTestId('employee-wizard-drawer-cancel').click();
  cy.get('[data-test-id="employee-wizard-drawer-close"]').click();

  // 用cy.wrap包裹spy,通过should断言调用次数
  cy.wrap(hideSpy).should('have.been.calledOnce');
});

方式2:给Spy起别名,通过别名断言

it.only('点击取消按钮时调用hide()一次', () => {
  // 给spy起别名,方便后续通过别名引用
  const hideSpy = cy.spy().as('hideSpy');

  cy.interceptEmployeeCreationWizard();
  cy.mount(
    <EmployeeCreationWizard
      isVisible={true}
      hide={hideSpy}
      employeeId={123}
    />,
  );

  cy.findByTestId('employee-wizard-drawer-cancel').click();
  cy.get('[data-test-id="employee-wizard-drawer-close"]').click();

  // 通过别名获取spy并断言
  cy.get('@hideSpy').should('have.been.calledOnce');
});

关键说明

  • Cypress的操作是异步的,直接用同步expect(hideSpy).to.be.calledOnce会因为断言时机过早导致失败,而should断言会自动重试直到条件满足或超时,完美适配Cypress的异步特性。
  • 两种方式都能实现需求,用别名的方式在复杂测试中更易维护,尤其是当需要多次引用同一个spy时。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 05:15:29