背景
我有一个使用Nx构建的单一代码库项目。这个代码库包含了多个后端项目可重用的库。这些库是从多个项目中收集而来,以创建一个可重用的库。
我使用 Jest 创建和运行在我的 monorepo 中使用的单元测试。
问题
当我运行 Jest 时,会在一些测试中抛出关于无法导入具有export
的 .js 文件的错误。
奇怪的是,这些模块有一个 commonjs 版本,我可以在其他没有 monorepo 结构的项目中轻松地模拟这些包。但是,当我在 monorepo 项目中使用相同的代码时(我想要使代码可重用),Jest 错误地导入了包的 ESM 版本而不是 CJS 版本。
用例:
- 我有一个 Blob 存储库,它在内部使用
ali-oss
。 ali-oss
在同一个包中分发了 CJS 和 ESM,并且我可以在其他项目中(不使用 monorepo)轻松地模拟它- 当我将相同的库复制到我的新 monorepo 中时,Jest 将抱怨
node_modules
中的ali-oss
源代码中有关于export
标记的问题
为什么 Jest 在 monorepo 和正常 repo 中的行为不同?如何解决这个奇怪的 jest 模块解析问题?
文件
tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": false,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"]
}
jest.config.ts:
const nxPreset = require("@nrwl/jest/preset").default;
export default {
...nxPreset,
clearMocks: true,
coverageReporters: ["lcov", "text", "text-summary", "json-summary"],
displayName: "kafka",
globals: {
"ts-jest": {
tsconfig: "<rootDir>/tsconfig.spec.json",
},
},
testEnvironment: "node",
transform: {
"^.+\\.[tj]s$": "ts-jest"
},
moduleFileExtensions: ["ts", "js"],
coverageDirectory: "../../coverage/packages/kafka",
};
单元测试:
import Bull from "bull";
import * as dlq from "../src/dlq";
import { ModuleContext} from "./context";
jest.mock("bull");
describe(ModuleContext.Root, () => {
describe(ModuleContext.Runner, () => {
it("success", () => {
expect(true).toBe(true);
})
describe(dlq.initialize.name, () => {
it("should return success", () => {
const createSpy = jest
.spyOn(Bull.prototype, "process")
.mockResolvedValue(null);
dlq.initialize();
expect(createSpy).toBeCalled();
});
});
});
});
Jest 输出:
FAIL kafka packages/kafka/test/dlq.spec.ts
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
/home/fahmi/logee/logee-ct/logeect-libraries-monorepo/node_modules/.pnpm/msgpackr@1.6.2/node_modules/msgpackr/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export { Packr, Encoder, addExtension, pack, encode, NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT, REUSE_BUFFER_MODE } from './pack.js'
^^^^^^
SyntaxError: Unexpected token 'export'
at Runtime.createScriptFromCode (../../node_modules/.pnpm/jest-runtime@28.1.3/node_modules/jest-runtime/build/index.js:1796:14)
at Object.<anonymous> (../../node_modules/.pnpm/bull@4.8.5/node_modules/bull/lib/scripts.js:8:18)