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

如何解决Cypress循环内调用cy.stub()触发重复包装报错问题

报错原因

循环中多次执行cy.stub(win, 'open')时,首次循环已经将window.open替换为stub模拟函数,第二次循环再次尝试包装同一个方法时,Cypress检测到目标方法已经被stub占用,就会抛出Attempted to wrap open which is already wrapped错误。
报错截图

修复方案

根据循环内是否会触发页面刷新,选择对应方案即可:

方案1:循环内不刷新页面(推荐)

如果循环过程中页面不会重载、window对象始终是同一个实例,只需要在循环外创建一次stub,每次循环开始前重置stub的历史调用记录即可,避免重复创建stub:

// 循环外仅初始化一次stub
cy.window().then((win) => {
  cy.stub(win, 'open').as('popup');
})

for (/* 你的循环逻辑 */) {
  // 清空上一次循环的stub调用记录
  cy.get('@popup').then(stub => stub.reset())

  // 执行触发弹窗的点击等操作
  // cy.get('触发弹窗的元素选择器').click()

  // 断言验证
  cy.get("@popup").should("be.called");
}

方案2:循环内会触发页面刷新/跳转

如果每次循环操作后页面会刷新、window对象会重建,那每次创建stub前先检查是否存在已有的stub,先恢复原始方法再创建新的stub:

for (/* 你的循环逻辑 */) {
  cy.window().then((win) => {
    // 若open方法已被stub,先恢复原始实现
    if (typeof win.open.restore === 'function') {
      win.open.restore()
    }
    cy.stub(win, 'open').as('popup');
  })

  // 执行触发弹窗的点击等操作
  // cy.get('触发弹窗的元素选择器').click()

  // 断言验证
  cy.get("@popup").should("be.called");
}

注意:Cypress默认只会在单个测试用例(it块)执行结束后自动恢复所有stub,同一个用例内的循环逻辑不会触发自动恢复,因此必须手动处理stub的复用或恢复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:09:23