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
相关产品推荐
相关产品推荐

