typescript - jestテスト内で new class() を呼び出しても新しいクラスインスタンスが作成されない
問題
ユニットテスト内で新しいクラスインスタンスを作成しても、コンストラクターは呼び出されません。
詳細
誤ったサーバーIPが指定されたときにエラーが発生するかどうかをテストしようとしていますが、エラーを投げるはずのクラスの新しいインスタンスを作成しようとすると、うまくいきません。
私がテストしようとしているクラスは次の通りです:
export class ClassA {
private readonly _redisServerIP = config.redisServerIP;
private readonly _redisServerPort = config.redisServerPort;
constructor() {
console.log(this._redisServerIP);
this.configure();
}
private configure(): void {
this._redisSub = redis.createClient({host: this._redisServerIP, port: this._redisServerPort});
this._redisSub.on('error', (error) => {
if (error.code === "ECONNREFUSED") {
this._logger.error('Could not create a redisSub, is the redis server running?');
}
throw new Error('Something bad happened');
});
}
}
これは私のテストコードです:
import * as constants from '../src/config/config';
let socket;
let classA;
let httpServerAddr;
beforeAll((done) => {
classA = new ClassA();
httpServerAddr = classA.getServerIp();
done();
});
afterAll((done) => {
done();
});
beforeEach((done) => {
});
afterEach((done) => {
done();
});
describe('Socket.io redis testing', () => {
test('should fail due to invalid serverIP', () => {
constants.config.redisServerIP = "0.0.0.0";
classA = null;
expect(() => {
classA = new ClassA();
}).toThrow();
});
});
ノードコンソールでサーバーのIPを一度だけ見ており、次のエラーのためにテストが失敗します:
expect(function).toThrow(undefined)
Expected the function to throw an error.
But it didn't throw anything.
これはすべてのテストがそれぞれ独自のプロミス内で実行されるからですか?そして、そのプロミス内で実行されているときにコンソールにログを出せないのですか?それとも、new ClassA() を呼び出す前に既存の ClassA のインスタンスをクリアしていない私のせいですか?
======編集======
ブレークポイントを使用した後、コンストラクターが呼び出されることがわかりましたが、コンソールには書き込まれません。しかし、throwは発生しません。Redisの動作は次の通りです。もしエラーが発生した場合、名前が「error」のイベントがRedisサーバーに送信されますが、テスト実行時にはこれがトリガーされません。これをトリガーするのを待つにはどうすればよいでしょうか?
回答 #1
私は redisSub を public にして接続が失敗したときに process.exit(); を呼び出すことでこの問題を解決しました。ユニットテストでは process.exit() を spyOn して、それが呼び出されたかどうかを確認します。
これはテストコードです:
describe('Socket.io redis testing', () => {
test('should fail due to invalid serverIP', () => {
const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {});
constants.config.redisServerIP = "127.312.12.1";
classA.stopServer();
classA = null;
classA = new ClassA();
classA.redisSub.on('error', () => {
expect(mockExit).toHaveBeenCalledWith(1);
});
mockExit.mockRestore();
});
ClassA 内でのイベントの使用も機能したでしょうが、それが最も洗練された解決策だとは思いませんでした。
