私はテストライブラリノード-ジャスミンして以下の機能をテストユニットにしようとしているとのユニットテスト:ユニットは、機能をテストするとき避け副作用ときジャスミン
joinGame(participant) {
console.log('Joining game', participant);
if (this.getParticipants().length >= MAX_NUMBER_OF_PARTICIPANTS) {
throw new Error(`The game with id ${this.getId()} has reached the maximum amount of participants, ${MAX_NUMBER_OF_PARTICIPANTS}`);
}
this.addParticipant(participant);
this.incrementPlayerCount();
this.emit(actions.GAME_JOINED, participant);
// Is the game ready to start?
if (this.playerCount >= REQUIRED_NUMBER_OF_PARTICIPANTS) {
// Start game loop by initializing the first round
this.createRound();
}
}
ただし、コードパスのカップルがつながります私は関数の最後にあるthis.createRound()を呼び出します。 createRound()は、基本的にゲームループ、開始タイマー、および私が単体テストしている関数とは全く関係のないその他の副作用を初期化します。以下のテストを見てください:
it('should throw an error if a user tries to join a game with the maximum amount of participants has been reached',() => {
game = new Game();
// To test whenever there are two participants in the game
game.joinGame(hostParticipant);
game.joinGame(clientParticipant);
function testJoin() {
game.joinGame(joiningParticipant);
}
expect(testJoin).toThrow();
});
私がテストを実行すると、テストは私の意志に対して 'createRound()'を呼び出します。 'createRound()'はRoundインスタンスをインスタンス化し、カウントダウンタイマーを開始します。これにより、コマンドラインの 'npm test'コールは決して終了しません。テストはそれがテストの一部だと思うので。
以下は、私が考えて実装した多くのアプローチです。しかし、私はそれらのいずれかが "きれい"であるとは思わないが、そのためにあなたの意見を求めている。
アプローチ1:機能の代わりにテスト内にスタブ 'createRound()'を挿入します。これは正常に動作しますが、それは副作用を呼び出さないようにする正しい方法ですか?
アプローチ2: beforeEach/afterEachでゲームインスタンスを設定/解除してみてください。私はこのアプローチを成功させることを試みました。ただし、 'afterEach()'でゲームインスタンスをnullに設定すると、インスタンス化されたラウンドインスタンスはそのタイマーに沿って継続します。
アプローチ3: 'joinGame()'を呼び出してRoundインスタンスを提供するときは、依存関係注入を使用します。しかし、これはあまり意味がありません。なぜなら、 'joinGame()'を呼び出すときに、新しいラウンドインスタンスを提供するのはクライアントの責任であってはならないからです。さらに、 'joinGame()'へのすべての呼び出しが 'createRound()'を呼び出すわけではありません。プレイヤー数が必要なプレイヤー数を超えた場合に限ります。