将cy.on移至Cypress自定义命令后失效的原因是什么?
Cypress自定义命令中window.open Stub失效问题解析
问题场景
原本在测试代码中定义的本地函数可以正常检测window.open调用并断言:
// 本地stub函数 const stubWindowOpen = () => { const stub = cy.stub().as(`window-open`) cy.on(`window:before:load`, (window) => { cy.stub(window, `open`).callsFake(stub) }) } // 断言函数 const assertWindowOpened = (url) => { cy.get(`@window-open`).should(`have.been.calledOnce`) cy.get(`@window-open`).should(`be.calledWith`, url, `_blank`) }
将stubWindowOpen转为/support/commands.js中的自定义命令后,断言失败,提示:
expected window-open to have been called exactly once, but it was never called
失效原因
核心问题在于**cy.stub()命令的异步特性**与window:before:load事件的同步触发时机不匹配:
- 在
window:before:load的回调中使用cy.stub()时,该命令会被加入Cypress的异步命令队列,而非立即执行 window:before:load事件是同步触发的,回调执行完成后,页面代码可能随即调用window.open,此时队列中的cy.stub操作还未执行,原生window.open方法并未被替换,导致stub从未被调用- 本地函数能正常工作是因为测试代码的执行调度刚好让
cy.stub在window.open调用前完成,但转为自定义命令后,命令队列的调度顺序打破了这个时机
修复方案
在window:before:load回调中同步替换window.open,直接使用stub赋值而非cy.stub()命令:
// /support/commands.js Cypress.Commands.add(`stubWindowOpen`, () => { const stub = cy.stub().as(`window-open`) cy.on(`window:before:load`, (window) => { // 同步替换window.open,确保立即生效 window.open = stub }) })
验证方式
测试代码中按正常顺序调用即可:
cy.stubWindowOpen() cy.visit('/your-page') // 触发打开新窗口的操作 cy.get('#open-window-btn').click() assertWindowOpened('https://target-url.com')
内容的提问来源于stack exchange,提问作者PBrown
相关产品推荐
相关产品推荐

