Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 使用Jasmine进行单元测试时避免副作用_Node.js_Unit Testing_Jasmine - Fatal编程技术网

Node.js 使用Jasmine进行单元测试时避免副作用

Node.js 使用Jasmine进行单元测试时避免副作用,node.js,unit-testing,jasmine,Node.js,Unit Testing,Jasmine,我正在尝试使用测试库节点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

我正在尝试使用测试库节点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:尝试在每次之前/之后设置/删除游戏实例。我尝试过这种方法,但没有成功。但是,通过在“afterEach()”上将游戏实例设置为null,实例化的round实例将继续执行其计时器


方法3:调用“joinGame()”时使用依赖项注入,并提供一个Round实例。不过,这没有多大意义,因为在调用“joinGame()”时,客户机不应该负责提供新的一轮实例。此外,并非每个对“joinGame()”的调用都会调用“createRound()”;只有当玩家数量超过所需的玩家数量时。

存根
createRound
当然有意义。您正在编写一个测试来断言拒绝用户加入完整游戏的行为,而不是计时器是否按预期工作。如果您在测试对象上存根一个方法,这会有点麻烦,但是我认为管理计时器的逻辑可能属于它自己的单独对象

当然,您也可以考虑:

方法4:模拟茉莉花中描述的时钟。假设计时器依赖于
setTimeout
/
setInterval
,则可以在调用函数之前安装假时钟,并手动勾选时钟以获取可以断言的状态