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

Cypress中验证别名存在或在if语句中比较别名文本的问题

解决方案

你可以通过两种方式解决这个问题,核心是绕过Cypress异步命令的限制,正确检测令牌状态并抛出自定义错误:

方法一:使用Cypress环境变量存储令牌(更简洁)

利用Cypress环境变量的同步访问特性,替代别名存储令牌,这样可以直接在callAPI中同步检查令牌状态:

  1. 修改登录方法,将令牌存入环境变量
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);
  });
}
  1. 更新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);
  }
}

方法二:使用别名+异步链式检查

如果需要保留别名存储,可以通过初始化默认值+异步链式调用的方式实现检查:

  1. 在测试上下文初始化令牌别名默认值
    在你的测试文件的before钩子中添加:
before(() => {
  // 初始化默认值,避免cy.get('@accessToken')报错
  cy.wrap('accessToken not set').as('accessToken');
});
  1. 修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 19:40:58