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

Next.js+Turbo环境下Cypress组件测试next/image多图Mock求助

解决Next.js 15 + Cypress 14 + Turbo环境下next/image组件的Mock问题

针对你遇到的多图Mock串图、正则拦截404以及修改组件默认导出报错的问题,以下提供两种可行的解决方案:

方案一:改进请求拦截,动态匹配对应图片

通过解析_next/image请求的URL参数,准确匹配组件中使用的原始图片路径,返回对应图片资源:

describe('<Home />', () => {
  it('renders with correct individual images', () => {
    // 映射组件中使用的图片src到本地文件路径
    const imageSrcMap = {
      '/assets/bard.webp': 'src/assets/bard.webp',
      '/assets/elf.webp': 'src/assets/elf.webp',
      '/assets/dnddice.webp': 'src/assets/dnddice.webp',
    };

    // 预加载所有图片并缓存数据
    const cachedImages: Record<string, { buffer: ArrayBuffer; contentType: string }> = {};

    cy.wrap(Object.entries(imageSrcMap)).each(([componentSrc, localPath]) => {
      return cy.readFile(localPath, null).then((img) => {
        // 根据文件后缀自动识别Content-Type
        const fileExt = localPath.split('.').pop();
        const contentType = fileExt === 'webp' ? 'image/webp' : `image/${fileExt}`;
        cachedImages[componentSrc] = { buffer: img.buffer, contentType };
      });
    }).then(() => {
      // 拦截所有Next.js图片优化请求,动态返回对应图片
      cy.intercept('_next/image*', (req) => {
        // 解析并解码请求中的原始图片路径参数
        const urlParams = new URLSearchParams(req.url.split('?')[1]);
        const originalSrc = decodeURIComponent(urlParams.get('url') || '');

        // 匹配缓存的图片数据并返回
        const targetImage = cachedImages[originalSrc];
        if (targetImage) {
          req.reply({
            statusCode: 200,
            headers: { 'Content-Type': targetImage.contentType },
            body: targetImage.buffer,
          });
        } else {
          req.reply({ statusCode: 404 });
        }
      });

      cy.mount(<Home />);
    });
  });
});

关键改进点

  • 解析并解码_next/image请求中的url参数,确保匹配组件中使用的原始图片路径
  • 预加载所有需要的图片并缓存,避免重复读取文件
  • 根据文件后缀自动设置Content-Type,适配不同图片格式

方案二:直接Mock next/image组件为原生img

跳过Next.js图片优化流程,将next/image替换为原生<img>标签,彻底避免_next/image请求:

  1. 在Cypress组件测试支持文件(cypress/support/component.ts)中添加Mock逻辑:
import * as NextImage from 'next/image';

// 创建Mock组件,渲染原生img标签
const MockNextImage = (props: React.ComponentProps<typeof NextImage.default>) => {
  const { src, alt, width, height, className, ...restProps } = props;
  return <img src={src} alt={alt} width={width} height={height} className={className} {...restProps} />;
};

// 在测试运行前替换next/image的默认导出
Cypress.on('test:before:run', () => {
  cy.stub(NextImage, 'default').callsFake(MockNextImage);
});
  1. 测试文件中直接挂载组件即可:
describe('<Home />', () => {
  it('renders all images correctly', () => {
    cy.mount(<Home />);
    // 可添加断言验证图片渲染
    cy.get('img[alt="Bard"]').should('have.attr', 'src', '/assets/bard.webp');
  });
});

优势

  • 无需处理复杂的请求拦截逻辑
  • 完全适配Turbo构建环境,不依赖Webpack配置
  • 组件渲染逻辑更贴近原生,减少测试环境差异

问题原因分析

  1. 多图拦截404:你之前的正则未考虑_next/image请求中url参数是URL编码后的字符串,直接匹配原始文件名会失败,解析并解码参数后即可解决。
  2. 修改默认导出报错:Next.js 15将next/image的默认导出设置为不可配置属性,使用cy.stub替换是更可靠的方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:50:16