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

Cypress自动保存拦截API响应为fixture文件问题排查

问题原因

原有代码无法生成fixture文件的核心原因:

  • cy.* 系列命令必须加入Cypress全局串行命令队列才能被调度执行,req.continue() 传入的响应回调是网络层触发的独立异步回调,不属于Cypress命令链上下文,这里直接调用cy.writeFile不会被Cypress识别执行,因此没有实际写文件操作。
  • console.log是浏览器原生API,不需要走Cypress调度,所以能正常打印日志,造成代码执行到写文件步骤的错觉。
  • 额外隐患:如果匹配的URL带查询参数、多层路径,直接拼接的文件路径可能包含非法文件名字符、不存在的父目录,即使writeFile执行也会失败。
正确实现步骤

第一步:(可选但推荐)在Cypress配置中注册Node层写文件任务

如果需要自动创建多级目录、格式化JSON内容,推荐在cypress.config.js中注册task,利用Node原生fs模块处理文件操作,稳定性更高:

const { defineConfig } = require("cypress");
const fs = require('fs');
const path = require('path');

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      on('task', {
        saveFixture({ filePath, content }) {
          const fullPath = path.join(config.fixturesFolder, filePath);
          // 递归创建父目录,避免多级路径写入失败
          fs.mkdirSync(path.dirname(fullPath), { recursive: true });
          // 格式化写入JSON,方便后续手动修改查看
          const writeContent = typeof content === 'object' 
            ? JSON.stringify(content, null, 2) 
            : content;
          fs.writeFileSync(fullPath, writeContent);
          return null;
        }
      })
    }
  }
})

第二步:修改saveResponse方法

核心是把Cypress命令包装成Cypress.Promise返回,让Cypress拦截逻辑等待写文件操作完成,同时处理路径中的非法字符:

const saveResponse = (req) => {
  req.continue((res) => {
    // 处理文件路径:移除域名、去掉查询参数、拼接json后缀
    const filePath = req.url
      .replace('https://covfefe/', '')
      .split('?')[0] + '.json';
    console.log('saving fixture to', filePath);

    // 使用自定义task写文件(推荐,兼容性更好)
    return new Cypress.Promise((resolve) => {
      cy.task('saveFixture', { filePath, content: res.body }, { log: false })
        .then(resolve);
    });

    // 如果不想修改配置,直接用内置cy.writeFile,可替换上面的Promise逻辑
    // return new Cypress.Promise((resolve) => {
    //   cy.writeFile(`cypress/fixtures/${filePath}`, res.body, { log: false })
    //     .then(resolve);
    // });
  })
}
后续使用建议

第一次运行测试用例时,Cypress会自动把所有匹配规则的接口响应存到对应fixture路径下。后续测试只需要修改拦截逻辑,优先读取本地fixture,不存在时再走真实请求并自动缓存,不需要重复修改代码:

// 通用拦截逻辑,可放在support/commands.js里全局生效
const autoFixtureHandler = (req) => {
  const filePath = req.url
    .replace('https://covfefe/', '')
    .split('?')[0] + '.json';
  // 先尝试读本地fixture
  cy.fixture(filePath, { timeout: 50 }).then((fixture) => {
    req.reply(fixture);
  }).catch(() => {
    // 本地不存在fixture时走真实请求,自动保存
    req.continue((res) => {
      return new Cypress.Promise((resolve) => {
        cy.task('saveFixture', { filePath, content: res.body }, { log: false })
          .then(() => resolve());
      });
    });
  });
}

// 测试用例里直接传入handler即可
cy.intercept('https://covfefe/redfish/v1/Chassis/Asrock/PCIeDevices/**', autoFixtureHandler)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:09:18