Cypress中验证别名存在或在if语句中比较别名文本的问题
解决方案
你可以通过两种方式解决这个问题,核心是绕过Cypress异步命令的限制,正确检测令牌状态并抛出自定义错误:
方法一:使用Cypress环境变量存储令牌(更简洁)
利用Cypress环境变量的同步访问特性,替代别名存储令牌,这样可以直接在callAPI中同步检查令牌状态:
- 修改登录方法,将令牌存入环境变量
logInAndSetAccessToken(emailAddress: string, password: string) { return this.callAPI({ requestObject: { method: 'POST', url: APIURLs.Login, body: { email: emailAddress, password: password } }, useAccessToken: false }).then(response => { // 将令牌存入Cypress环境变量 Cypress.env('accessToken', response.body.tokens.accessToken); }); }
- 更新
callAPI方法,同步检查令牌
callAPI({ url = '', requestObject = {}, useAccessToken = true } = {}) { // 保留原有参数校验逻辑 if (url.length > 3 && Object.keys(requestObject).length > 0) { throw new Error('callAPI() - method call ambiguous. Pass url or requestObject, not both.'); } if (url.length < 4 && Object.keys(requestObject).length == 0) { throw new Error('callAPI() - method call missing necessary information to make API call. Pass url or requestObject.'); } // 同步检查令牌状态 if (useAccessToken) { const accessToken = Cypress.env<string>('accessToken'); if (!accessToken) { throw new Error('callAPI() - access token not set. Log in first.'); } } if (Object.keys(requestObject).length > 0) { if (!requestObject.method || !requestObject.url || !requestObject.body) { throw new Error('callAPI() - method, url or body properties are missing in the requestObject.'); } if (!requestObject.headers) { requestObject.headers = {}; } if (!requestObject.headers['Content-Type']) { requestObject.headers['Content-Type'] = 'application/json; charset=utf-8'; } // 自动添加授权头 if (useAccessToken && !requestObject.headers['Authorization']) { const accessToken = Cypress.env<string>('accessToken'); requestObject.headers['Authorization'] = `Bearer ${accessToken}`; } return cy.request(requestObject); } else { if (url.length < 4) { throw new Error('callAPI() - invalid url, cannot call API.'); } // 处理url模式的授权头添加 if (useAccessToken) { const accessToken = Cypress.env<string>('accessToken'); return cy.request({ url, headers: { 'Authorization': `Bearer ${accessToken}` } }); } return cy.request(url); } }
方法二:使用别名+异步链式检查
如果需要保留别名存储,可以通过初始化默认值+异步链式调用的方式实现检查:
- 在测试上下文初始化令牌别名默认值
在你的测试文件的before钩子中添加:
before(() => { // 初始化默认值,避免cy.get('@accessToken')报错 cy.wrap('accessToken not set').as('accessToken'); });
- 修改
callAPI方法,异步检查令牌
callAPI({ url = '', requestObject = {}, useAccessToken = true } = {}) { // 保留原有参数校验逻辑 if (url.length > 3 && Object.keys(requestObject).length > 0) { throw new Error('callAPI() - method call ambiguous. Pass url or requestObject, not both.'); } if (url.length < 4 && Object.keys(requestObject).length == 0) { throw new Error('callAPI() - method call missing necessary information to make API call. Pass url or requestObject.'); } // 处理令牌检查逻辑,返回链式调用 const tokenCheck = useAccessToken ? cy.get<string>('@accessToken').then(token => { if (token === 'accessToken not set') { throw new Error('callAPI() - access token not set. Log in first.'); } return token; }) : cy.wrap(null); return tokenCheck.then(token => { let finalRequest = { ...requestObject }; if (Object.keys(finalRequest).length > 0) { if (!finalRequest.method || !finalRequest.url || !finalRequest.body) { throw new Error('callAPI() - method, url or body properties are missing in the requestObject.'); } if (!finalRequest.headers) { finalRequest.headers = {}; } if (!finalRequest.headers['Content-Type']) { finalRequest.headers['Content-Type'] = 'application/json; charset=utf-8'; } if (useAccessToken && token && !finalRequest.headers['Authorization']) { finalRequest.headers['Authorization'] = `Bearer ${token}`; } return cy.request(finalRequest); } else { if (url.length < 4) { throw new Error('callAPI() - invalid url, cannot call API.'); } if (useAccessToken && token) { return cy.request({ url, headers: { 'Authorization': `Bearer ${token}` } }); } return cy.request(url); } }); }
关键说明
- 方法一利用
Cypress.env的同步特性,避免了异步链式调用的复杂度,更适合API自动化场景。 - 方法二则保留了别名的使用方式,适合需要与Cypress上下文深度绑定的场景。
- 两种方法都能在未登录时抛出你定义的自定义错误,无需依赖API自身的未授权提示。
内容的提问来源于stack exchange,提问作者Zuno
相关产品推荐
相关产品推荐

