未使用cy.should()却触发Cypress回调命令调用报错问题咨询
问题分析:Cypress报错未使用
should()却提示相关错误 问题场景
检查异步请求响应时,明明代码里没用到cy.should(),却抛出了should()回调内调用命令的错误,堆栈跟踪还指向expect校验响应状态的代码行。
核心代码片段(graphql.ts)
return cy.request({...}).then((response) => { expect(response.status, 'Invalid response status').to.equal(200) return cy.wrap(response.body.data) })
报错信息
CypressError: `cy.should()` failed because you invoked a command inside the callback. `cy.should()` retries the inner function, which would result in commands being added to the queue multiple times. Use `cy.then()` instead of `cy.should()`, or move any commands outside the callback function.
堆栈跟踪
> `cy.get()` at $Cypress.commandEnqueued (http://172.18.0.20/__cypress/runner/cypress_runner.js:135214:76) at $Cypress.listener (http://172.18.0.20/__cypress/runner/cypress_runner.js:86503:17) ... From Your Spec Code: at Context.eval (infra/api/graphql.ts:20:10)
补充完整调用栈
Then('updated pipeline is available via API', function (table) { cy .getUserInfo() .then(usr => { retryWithTimeout(retry => { requestGraphQL(pipelineQuery, usr.api_key, vars) .should(res => { cy.get(`@${Alias}`).then(alias => { if (somecondition) retry('Msg') .... }) }) }, { timeout: 120, delay: 20 }) }) }) const requestGraphQL = (body: string, authKey: string, vars: any = {}, url= graphqlUrlPath): Chainable => cyRequest(body, authKey, vars, url) const cyRequest = (queryStr: string, authKey: string, vars: any, url: string): Chainable<any> => { return cy.request({...}).then((response) => { expect(response.status, 'Invalid response status').to.equal(200) return cy.wrap(response.body.data) }) }
问题原因
根源是你在调用链上层的cy.should()回调里嵌套了cy.get()命令。
Cypress的should()特性是重复执行回调函数,直到断言通过或超时。如果回调里包含cy.get()这类Cypress命令,每次重试都会往命令队列里新增命令,导致队列混乱触发报错。
至于堆栈指向graphql.ts里的expect行,是因为requestGraphQL返回的链式调用被后续的should()包裹,Cypress内部调用链追溯时关联到了这个位置,但真正的错误触发点是should()回调里的cy.get()。
解决方案
把should()替换成then()即可,因为then()不会重试回调,适合处理包含命令逻辑的场景:
Then('updated pipeline is available via API', function (table) { cy .getUserInfo() .then(usr => { retryWithTimeout(retry => { requestGraphQL(pipelineQuery, usr.api_key, vars) .then(res => { // 将should替换为then cy.get(`@${Alias}`).then(alias => { if (somecondition) retry('Msg') .... }) }) }, { timeout: 120, delay: 20 }) }) })
如果原本需要用should()做断言,要把断言逻辑和命令逻辑分离:要么先通过then()执行命令再单独做断言,要么在should()回调里只放纯断言代码,不要嵌套任何Cypress命令。
内容的提问来源于stack exchange,提问作者Bogdan Pisarenko
相关产品推荐
相关产品推荐

