如何让配置文件同时被Rollup构建产物与Jest测试识别?
这个问题我之前也碰到过,核心是测试环境和生产环境下配置文件的路径解析逻辑不一致导致的:生产构建后配置文件会被拷贝到产物目录,所以运行时能正常读取;但Jest测试时是直接解析源码,greeter.ts里的./config.json会被解析为src/modules/config.json,而你把测试用配置放在了__tests__目录,自然找不到。下面给你几个可行的解决方案:
方案1:用Jest的moduleNameMapper映射配置路径
这是最简单直接的方法,通过Jest配置把源码里的配置路径映射到测试目录下的配置文件:
修改你的jest.config.ts,添加moduleNameMapper配置:
module.exports = { "verbose": true, "transform": { "^.+\\.tsx?$": "ts-jest" }, // 新增:将src/modules里的config.json映射到测试目录的配置文件 "moduleNameMapper": { "./config.json": "<rootDir>/__tests__/test.config.json" } };
注意:把
test.config.json换成你实际的测试配置文件名(比如你可以在__tests__下创建专门的测试配置)。
原理:Jest在解析greeter.ts里的require('./config.json')时,会自动替换成指向__tests__目录下的测试配置,同时不影响生产构建时的路径解析。
方案2:抽离配置模块并Mock(更符合测试隔离原则)
把配置读取逻辑抽成独立模块,测试时直接Mock这个模块的返回值,完全不需要依赖真实配置文件:
步骤1:重构配置读取逻辑
在src/modules下新建config.ts:
const config = require('./config.json'); export default config;
修改greeter.ts,导入这个模块:
import config from './config'; const greeting = config.greeting; console.log(greeting) export function greeter(name: string): string { return greeting + ", " + name }
步骤2:在测试中Mock配置模块
修改__tests__/greeter.test.ts:
import {greeter} from '../src/modules/greeter'; // Mock配置模块,直接返回测试所需的问候语 jest.mock('../src/modules/config', () => ({ greeting: 'hi' })); test('greeter使用配置文件中指定的问候语', () => { expect(greeter('ABC')).toBe('hi, ABC'); }); test('greeter使用运行时传入的名称参数', () => { expect(greeter('ABC')).toContain('ABC'); });
这个方案的优势是测试完全隔离,不需要维护额外的测试配置文件,适合单元测试场景。
方案3:通过环境变量动态加载配置
如果需要区分多个环境的配置,可以通过环境变量判断加载不同路径的配置:
步骤1:修改greeter.ts的配置加载逻辑
let config; // 根据环境变量判断加载路径 if (process.env.NODE_ENV === 'test') { config = require('../../__tests__/test.config.json'); } else { config = require('./config.json'); } const greeting = config.greeting; console.log(greeting) export function greeter(name: string): string { return greeting + ", " + name }
步骤2:给Jest设置测试环境变量
在package.json的test脚本中添加环境变量:
{ "scripts": { "test": "NODE_ENV=test jest --verbose --coverage --debug --env node" } }
或者在jest.config.ts里通过setupFiles提前设置:
module.exports = { "verbose": true, "transform": { "^.+\\.tsx?$": "ts-jest" }, "setupFiles": [ "<rootDir>/__tests__/setupEnv.ts" ] };
然后新建__tests__/setupEnv.ts:
process.env.NODE_ENV = 'test';
额外注意:确保生产构建时配置文件被正确拷贝
不管用哪个方案,都要保证Rollup构建时把src/modules/config.json拷贝到build目录,让产物能正常读取。你的package.json里已经有rollup-plugin-copy,可以在rollup.config.js里配置:
import copy from 'rollup-plugin-copy'; export default { input: 'src/index.ts', output: { file: 'build/app.js', format: 'cjs' }, plugins: [ // 其他插件... copy({ targets: [ { src: 'src/modules/config.json', dest: 'build' } ] }) ] };
内容的提问来源于stack exchange,提问作者Bojan Komazec

