NPM包中出现‘jest is not defined’错误的原因排查
错误原因分析
这个错误的核心问题是:你在应用的生产/开发运行环境(nest start启动的服务)中,导入了依赖Jest测试框架的代码。
jest.fn()和jest.Mock类型都是Jest专属的API,只有在执行jest测试命令时,Jest才会自动将jest对象挂载到全局作用域中。- 而
nest start是启动正常的应用服务,此时运行环境中没有全局的jest对象,也不应该加载任何测试相关依赖——哪怕你把Jest设为dependency,Node.js也不会自动为非测试环境注入全局jest,同时这也违背了依赖管理的原则(测试工具属于开发依赖,不该进入生产依赖)。
解决方案
1. 拆分测试工具代码
将所有Jest模拟代码从包的主导出中分离,放到单独的目录(比如test-utils),并在package.json中配置单独的导出入口:
// 你的NPM包package.json "exports": { ".": "./dist/index.js", "./test-utils": "./dist/test-utils/index.js" }
项目中只有在测试代码里才导入测试工具:
// 测试文件中导入 import { getDataSourceMock } from '@custom/my-library/test-utils';
应用的业务代码永远不会导入这些测试相关模块,从根源避免环境不兼容问题。
2. 避免依赖全局jest对象
如果必须在包中提供模拟工具,且希望兼容非测试环境(不推荐,因为这是测试专用工具),可以修改代码,让用户手动传入jest实例:
// 修改后的模拟代码,不依赖全局jest export type MockType<T> = { [P in keyof T]?: jest.Mock<unknown>; }; // 允许传入jest实例,避免依赖全局对象 export function createMockQueryRunner(jestInstance: typeof jest) { return { connect: jestInstance.fn(), startTransaction: jestInstance.fn(), release: jestInstance.fn(), commitTransaction: jestInstance.fn(), rollbackTransaction: jestInstance.fn(), manager: { update: jestInstance.fn(), }, }; } export function getDataSourceMock(jestInstance: typeof jest) { const mockQueryRunner = createMockQueryRunner(jestInstance); return { createQueryRunner: () => mockQueryRunner, }; }
用户在测试时需要手动传入全局jest:
import { getDataSourceMock } from '@custom/my-library'; const dataSourceMock = getDataSourceMock(jest);
3. 确保测试代码不被打包进生产构建
检查你的NPM包的构建配置(比如tsconfig.json),确保test-utils或__mocks__目录不会被包含在生产构建的输出中,或者在.npmignore中排除测试相关文件。
内容的提问来源于stack exchange,提问作者napfernandes
相关产品推荐
相关产品推荐

