Nestjs를 통해서 애플리케이션을 실행하게되면 자동으로 빌드가 먼저 되기 때문에 ts파일로 작성한 워커도 실제 런타임 환경에서는 js파일로 변환되어 있어 별다르게 손을 댈 필요가 없다.
하지만, Jest로 테스트를 진행할때는 빌드하지 않고 ts파일인채로 테스트를 하게되는데, 이때 워커 파일의 경로가 일치하지 않아서 테스트가 실패한다.
import * as path from 'path';
import { Worker } from 'worker_threads';
class LoggerWorker {
private readonly pool: Worker[] = [];
private readonly logDir = path.join(process.cwd(), 'logs');
private readonly workerPath = path.join(__dirname, 'worker.js');
private create() {
const workerData = { logDir: this.logDir };
const worker = new Worker(this.workerPath, { workerData });
this.pool.push(worker);
worker.on('exit', (code) => {
if (code !== 0) {
console.error(`Worker stopped with exit code ${code}`);
}
this.pool.pop();
});
}
public getWorker() {
if (this.pool.length === 0) {
this.create();
}
return this.pool[0];
}
}
export const logWorker = new LoggerWorker();
FAIL test/app.e2e-spec.ts (6.814 s)
AppController (e2e)
✕ / (GET) (178 ms)
● AppController (e2e) › / (GET)
Cannot find module '/Users/me/App/server/src/utilities/logger/worker.js'
런타임에서는 빌드된 경로인 /Users/me/App/server/dist/utilities/logger/worker.js를 찾아가기에 문제가 없지만, jest는 빌드되기 전 소스 경로를 찾아가기에 존재하지 않는 worker.js를 찾다가 테스트가 실패하는 것이다.
이런 문제는 Nestjs가 아닌 타 프레임워크에서 ts-node로 애플리케이션을 실행하는 경우에도 발생하는데, 이럴 때는 해당 위치에 worker.ts 파일을 읽어오는 js파일을 만들어야 한다.
const path = require('path');
const workerPath = path.join(__dirname, 'worker.js');
require('ts-node').register();
require(path.resolve(__dirname, workerPath));
다시 테스트를 해보면 정상적으로 워커가 실행되고 테스트를 통과할 수 있다.