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

pnpm迁移后Jest测试中Mantine createStyles颜色未定义问题

问题解答与解决方案

问题1:类似问题与原因推测

这类问题在npm迁移pnpm的场景中并不少见,核心原因集中在以下几点:

  • pnpm的依赖隔离特性:pnpm采用严格的依赖隔离机制(通过软链接+内容寻址存储),可能导致Jest环境下加载了多个@mantine/core或@mantine/styles实例,使得Mantine的ThemeContext无法跨实例共享,最终createStyles拿到的是默认主题而非自定义主题。
  • react-app-rewired兼容性问题:react-app-rewired针对npm的扁平化依赖结构设计,在pnpm环境下可能未正确修改Jest的模块解析配置,导致测试环境的主题注入逻辑失效。
  • Jest缓存残留:迁移后模块路径发生变化,但Jest缓存的旧解析信息未更新,导致自定义主题未被正确加载。

问题2:pnpm为何影响Jest

npm采用扁平化依赖结构,所有依赖尽可能提升到根node_modules;而pnpm采用隔离式依赖管理,每个包的依赖独立存储并通过软链接关联。这种差异直接导致:

  • 多实例冲突:Jest可能加载到多个相同包的实例,破坏了Mantine主题上下文的单例模式,使得Provider传递的自定义主题无法被createStyles获取。
  • 配置失效:react-app-rewired的原有配置无法适配pnpm的依赖路径,导致Jest测试环境缺少必要的模块解析规则,主题注入逻辑异常。
  • 环境不一致:测试环境的模块解析逻辑与开发/生产环境脱节,出现仅测试阶段主题不生效的情况。

可尝试的解决方案

1. 清除缓存并重新安装依赖

# 清除Jest缓存
npx jest --clearCache

# 清除pnpm缓存并重装依赖
pnpm store prune
pnpm install

2. 强制Jest使用单一Mantine实例

在config-overrides.js中添加Jest模块解析配置,避免多实例冲突:

module.exports = {
  jest: function (config) {
    // 强制映射到根node_modules中的Mantine模块
    config.moduleNameMapper = {
      ...config.moduleNameMapper,
      '@mantine/core': '<rootDir>/node_modules/@mantine/core',
      '@mantine/styles': '<rootDir>/node_modules/@mantine/styles',
    };

    // 添加别名确保解析到单一实例
    config.resolve.alias = {
      ...config.resolve.alias,
      '@mantine/core': require.resolve('@mantine/core'),
      '@mantine/styles': require.resolve('@mantine/styles'),
    };

    return config;
  },
};

3. 手动在测试中注入自定义主题

如果上述方法无效,可在测试文件中直接为createStyles提供自定义主题:

import { theme } from '../path/to/your/theme';
import { createStyles } from '@mantine/styles';

// Mock createStyles,强制使用自定义主题
jest.mock('@mantine/styles', () => ({
  ...jest.requireActual('@mantine/styles'),
  createStyles: (styleFn) => styleFn(theme),
}));

4. 验证主题上下文传递

添加测试代码确认主题是否正确传入测试环境:

import { ThemeContext } from '@mantine/core';
import { render, screen } from '@testing-library/react';
import { Providers } from '../path/to/Providers';

test('验证自定义主题是否传递', () => {
  render(
    <Providers>
      <ThemeContext.Consumer>
        {(theme) => (
          <div data-testid="theme-colors">{JSON.stringify(theme.colors)}</div>
        )}
      </ThemeContext.Consumer>
    </Providers>
  );
  
  const themeColors = screen.getByTestId('theme-colors').textContent;
  console.log('测试环境主题颜色:', themeColors);
  // 断言自定义颜色存在
  expect(themeColors).toContain('white');
});

5. 替换react-app-rewired为craco

如果react-app-rewired兼容性问题无法解决,可尝试使用craco(Create React App Configuration Override),它对pnpm的支持更完善:

# 安装craco
pnpm install @craco/craco --save-dev

修改package.json的脚本:

{
  "scripts": {
    "test": "craco test --env=jsdom"
  }
}

创建craco.config.js并添加必要的Jest配置。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 04:05:55