Cypress如何获取登录响应token并添加到所有请求头
问题原因
你的代码不生效核心是两个问题:
cy.intercept注册时机错误:你把拦截逻辑写在了登录请求的回调里,Cypress的拦截器只有注册完成后才会捕获匹配的请求,测试过程中页面初始化、资源加载的早期请求很可能在拦截器注册前就已经发出,自然带不上token。- 缺少前端登录态同步:很多应用启动时会优先从本地存储(localStorage/sessionStorage、Cookie)读取token判断登录状态,你只给后续请求加了请求头,没有同步前端存储的登录态,前端本身就会判定用户未登录。
正确实现方案
第一步:提前全局注册请求拦截器
不要等登录回调里再注册拦截器,直接在测试支持文件(一般是cypress/support/commands.js或cypress/support/e2e.js)的beforeEach钩子中提前注册,保证所有应用发起的请求都能被捕获:
beforeEach(() => { // 匹配所有需要带token的请求,如果只需要拦截接口可以把*换成你的接口前缀,比如'/api/*' cy.intercept({ url: '*' }, (req) => { // 仅当获取到有效token时才添加请求头,避免给登录请求本身加无效token const token = Cypress.env('authToken') if (token) { req.headers['token'] = token } // 显式放行请求,兼容不同Cypress版本的逻辑 req.continue() }) })
第二步:优化自定义登录命令
登录拿到token后,把token存在Cypress全局环境变量中供拦截器读取,同时根据你应用的存储逻辑,把token同步到前端本地存储中,保证前端初始化时能读到登录态:
// 提前配置好的测试账号凭据 const creds = { login: 'your_test_username', password: 'your_test_password' } Cypress.Commands.add('login', () => { return cy.request({ method: 'POST', url: 'site/login', form: true, body: { username: creds.login, password: creds.password } }).then((resp) => { const token = resp.body.token // 把token存入Cypress环境变量,拦截器可以动态读取最新值 Cypress.env('authToken', token) // 👇 根据你应用的实际存储逻辑选对应的配置即可,不需要全加 // 如果应用从localStorage读取token cy.window().then(win => win.localStorage.setItem('token', token)) // 如果应用从sessionStorage读取token // cy.window().then(win => win.sessionStorage.setItem('token', token)) // 如果应用从cookie读取token // cy.setCookie('token', token) return token }) })
第三步:测试用例按正确顺序调用
用例中一定要先完成登录、拿到token之后,再访问测试页面,避免页面初始化请求漏带token:
describe('需要登录的业务流程测试', () => { it('正常访问登录后首页', () => { // 先执行登录 cy.login() // 登录完成后再访问页面 cy.visit('/user/dashboard') // 后续所有业务请求都会自动携带token cy.get('.user-info').should('be.visible') }) })
常见避坑点
- 确认请求头名称和后端要求完全一致,部分后端要求的头名是
Authorization,格式为Bearer ${token},不要写错头名或格式。 - 如果不需要给静态资源(js、css、图片)加token,把拦截规则的url匹配范围缩小到接口路径,能提升测试运行稳定性。
- 不要在
cy.visit()之后才调用cy.login(),页面加载过程中发出的请求会早于登录逻辑执行,必然带不上token。
内容的提问来源于stack exchange,提问作者Yaroslav Fomin
相关产品推荐
相关产品推荐

