node.js - Awilix در بارگذاری خودکار ماژولها در تستها با تنظیمات TypeScript شکست میخورد
من از تایپاسکریپت، ویتست، آویلیکس استفاده میکنم:
"typescript": "^5"
"vitest": "^1"
"awilix": "^8"
در اینجا ساختار دایرکتوری من است:
./
├── tsconfig.json
├── vitest.config.mts
./src/
├── Connection
│ └── Mongoose.ts
├── Core
│ └── Container.ts
└── init.ts
./test/
├── Connection
│ └── Mongoose.test.ts
├── Core
│ └── Container.test.ts
└── tsconfig.json
این فایل ریشه من است ./tsconfig.json:
{
"extends": "@tsconfig/node-lts/tsconfig.json",
"compilerOptions": {
"lib": ["WebWorker", "ESNext", "ES2022", "DOM"],
"rootDir": ".",
"outDir": "build",
"esModuleInterop": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"allowSyntheticDefaultImports": true,
"importHelpers": true,
"alwaysStrict": true,
"sourceMap": true,
"declaration": true,
"declarationDir": "./build/@types",
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitAny": false,
"noImplicitThis": false,
"strictNullChecks": true,
"useUnknownInCatchVariables": true,
},
"types": ["node"],
"include": ["src/**/*.ts", ".eslintrc.js"],
"exclude": ["node_modules", "**/node_modules/*", "**/dist/*", "**/build/*"]
}
این فایل vitest.config.mts من است:
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
environment: "node",
globals: true,
include: ['test/**/*.test.ts'],
exclude: ['**/node_modules/**', '**/dist/**', '**/build/**'],
deps: {
moduleDirectories: ["node_modules"],
},
coverage: {
all: true,
provider: "v8",
reportsDirectory: "./coverage",
enabled: true,
include: ['src/**/*'],
reporter: [
"text",
"json",
"html",
"lcov",
"clover",
"json-summary",
"text-summary",
],
},
poolOptions: {
threads: {
singleThread: true,
},
},
},
});
من تلاش میکنم ماژولها را با استفاده از Awilix و تابع loadModules() بهطور خودکار بارگذاری کنم.
در اینجا اسکریپت src/Core/Container.ts من است که برای کل برنامهام کانتینر ایجاد میکنم:
import { resolve } from "path";
import {
createContainer,
AwilixContainer,
Lifetime,
asClass,
} from "awilix";
export interface Cradle {}
export default async (): Promise<AwilixContainer<Cradle>> => {
const container = createContainer();
container.loadModules(
[
`${resolve(__dirname, "../Connection/*.js")}`,
`${resolve(__dirname, "../Connection/**/*.js")}`,
],
{
resolverOptions: {
lifetime: Lifetime.SINGLETON,
register: asClass,
},
}
);
return container;
};
وقتی تلاش میکنم container.registrations را خارج از هر آزمون ببینم، همه چیز خوب پیش میرود و میتوانم با استفاده از container.resolve('Mongoose'); آن را حل کنم
init.ts
import initContainer from "src/Core/Container";
export default async (): Promise<void> => {
const container = await initContainer();
console.log(container.resolve("Mongoose")); // Prints: Mongoose {}
};
اما Awilix ماژولها را وقتی که من کانتینر را در تستهایم ایجاد میکنم بارگذاری نمیکند:
Mongoose.test.ts
import initContainer from "src/init";
describe("Mongoose", () => {
it("Connect", async () => {
const container = await initContainer();
console.log(container.registrations); // Prints: {}
expect(true).toBeTruthy();
});
});
تا جایی که من میدانم، همه چیز به دلیل فایل ./tsconfig.json من در دایرکتوری build/ ساخته میشود. همانطور که میبینیم دایرکتوری test/ در آن گنجانده نشده است ("include": ["src/**/*.ts", ".eslintrc.js"]).
من توانستم آن را با اضافه کردن دایرکتوری test/ برای ساخته شدن توسط tsc حل کنم. همچنین مجبور شدم vitest.config.mts خود را تغییر دهم تا تستها از build/test/ اجرا شوند.
جدید vitest.config.mts:
export default defineConfig({
test: {
// ...
include: ["build/test/**/*.test.js"],
// exclude: ["**/node_modules/**", "**/dist/**", "**/build/**"],
coverage: {
// ...
include: ["build/src/**/*"],
},
// ...
},
});
اما مطمئن نیستم که این یک راهحل مناسب برای گنجاندن تستها در build/dist و اجرای نسخه ساختهشده باشد.
همچنین من نمیخواهم از type: module در package.json خود استفاده کنم.
من به جای vitest از jest: "^29" استفاده کردم و با همان مشکل روبرو شدم.
jest.config.ts
import { type JestConfigWithTsJest } from 'ts-jest';
const jestConfig: JestConfigWithTsJest = {
testRegex: '(/test/.*\\.(test|spec))\\.(ts|js)$',
testPathIgnorePatterns: ['/lib/', '/node_modules/'],
moduleFileExtensions: ['ts', 'js', 'json', 'node'],
collectCoverage: true,
};
export default jestConfig;
آیا کسی میتواند به من در این مشکل کمک کند؟