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

如何在Cypress测试中两次Stub prompt方法?问题排查与解决

问题:单条Cypress测试用例中两次Stub prompt失败,仅第一个生效

在单条测试用例中,需完成「创建文件夹→重命名文件夹」的流程,两个操作均依赖外部prompt弹窗,需要分别Stub,但实际仅第一个Stub生效,同时报错:Attempted to wrap prompt which is already wrapped。

以下是文件夹创建方法(单场景测试可正常运行):

addFolder(folderName) {
    let stub;

    cy.window().then(win => {
      stub = cy.stub(win, 'prompt').returns(folderName)  // 填入文件夹名称
    })
    
    cy.get(this.addFolderButtonLocator).click()
    
    cy.wrap(stub).should(() => {
      expect(stub).to.have.been.calledWith()
    })

    return this;
}

以下是文件夹重命名方法(仅调用第一个方法的Stub):

rename(name, newName) {
    let stub;

    cy.window().then(win => {
      stub = cy.stub(win, 'prompt').returns(newName)  // 填入新名称
    })
    
    this.invokeSideMenu(name);
    cy.get(`[data-cy="${name}-rename"]`).click();
    
    cy.wrap(stub).should(() => {
      expect(stub).to.have.been.calledWith()
    })

    return this;
}

问题原因

  1. 重复Stub未清理:Cypress的cy.stub()包裹window.prompt后,不会自动恢复原方法,第二次尝试Stub时,原方法已被包裹,触发报错。
  2. 全局Stub未隔离:两次Stub直接覆盖全局的prompt,第一个Stub未失效前,第二个Stub无法替换生效。

解决方案

方案一:每次Stub后恢复原方法

在每个操作的断言完成后,调用stub.restore()恢复prompt的原始实现,避免重复包裹报错。

修改后的创建文件夹方法:

addFolder(folderName) {
  let stub;

  cy.window().then(win => {
    stub = cy.stub(win, 'prompt').returns(folderName)
  })
  
  cy.get(this.addFolderButtonLocator).click()
  
  cy.wrap(stub).should(() => {
    expect(stub).to.have.been.calledWith()
  }).then(() => {
    stub.restore() // 恢复原生prompt方法
  })

  return this;
}

修改后的重命名方法:

rename(name, newName) {
  let stub;

  cy.window().then(win => {
    stub = cy.stub(win, 'prompt').returns(newName)
  })
  
  this.invokeSideMenu(name);
  cy.get(`[data-cy="${name}-rename"]`).click();
  
  cy.wrap(stub).should(() => {
    expect(stub).to.have.been.calledWith()
  }).then(() => {
    stub.restore() // 恢复原生prompt方法
  })

  return this;
}

方案二:单Stub处理多次调用(更简洁)

如果两次prompt的调用顺序固定,可通过单个Stub依次返回不同值,无需在每个方法内单独Stub:

it('创建并重命名文件夹', () => {
  cy.window().then(win => {
    cy.stub(win, 'prompt')
      .onFirstCall().returns('初始文件夹') // 第一次prompt返回创建名称
      .onSecondCall().returns('新文件夹名') // 第二次prompt返回重命名名称
  })

  // 执行流程
  yourPageObject.addFolder('初始文件夹')
  yourPageObject.rename('初始文件夹', '新文件夹名')
})

注意事项

  • 方案一中的restore()需在断言完成后执行,避免影响操作流程。
  • 方案二需确保prompt的调用顺序与Stub的onFirstCall/onSecondCall顺序完全匹配,否则会返回错误值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 04:18:22