【发布时间】:2018-06-01 01:15:44
【问题描述】:
我正在尝试使用测试库 node-jasmine 对以下函数进行单元测试:
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 上设置/拆除 Game 实例。我试过这种方法没有成功。但是,通过在 'afterEach()' 上将游戏实例设置为 null,实例化的回合实例会继续与其计时器一起运行。
方法 3: 在调用 'joinGame()' 并提供 Round 实例时使用依赖注入。但这并没有多大意义,因为在调用“joinGame()”时提供一个新的回合实例不应该是客户的责任。此外,并非每次调用“joinGame()”都会调用“createRound()”;仅当玩家人数超过所需玩家人数时。
【问题讨论】:
标签: node.js unit-testing jasmine