【问题标题】:NodeJS: How to verify a function call inside promise resolution while testing using Mocha, Chai, Sinon?NodeJS:如何在使用 Mocha、Chai、Sinon 进行测试时验证 Promise 解析中的函数调用?
【发布时间】:2017-09-24 12:01:03
【问题描述】:

我是使用 Mocha、Chai 和 Sinon 在 NodeJS 中进行单元测试的新手。我一直在尝试为 API 端点编写单元测试用例,并且正在努力测试是否在 Promise 解决方案中从 API 调用 res.status(200).send();。下面是代码:

controller.js - 有待单元测试的功能

const User = require("./user_model");

module.exports = {
    getUserById(req, res) {
        const { params: reqParams } = req,
            { userId } = reqParams;

        User.findOne({ _id: userId })
            .exec()
            .then(function(userFromDb) {
                res.status(200).send();    // unable to test if this is getting called.
            })
            .catch((err) => res.status(500).send());
    }
};

test.js - 有单元测试

const sinon = require("sinon"),
    User = require("./user_model"),
    controller = require("../controller");

require("sinon-mongoose");

describe('users', function() {
    it('getUserById', function() {
        const validReqObj = {
            params: {
                userId: "123"
            }
        };

        const mock = sinon.mock(User);
        mock.expects("findOne").withArgs({ _id: validReqObj.params.userId })
            .chain("exec")
            .resolves({ _id: validReqObj.params.userId });

        const validRes = {
            status: function(statusCode) {
                sinon.assert.match(statusCode, 200);

                return {
                    send: function() {

                    }
                };
            }
        };

        controller.getUserById(validReqObj, validRes);

        mock.restore();
        mock.verify();
    });
});

如你所见,我的测试做了两件事:

  1. 模拟猫鼬findOne 函数并测试findOne 的承诺解析是否正常。
  2. 断言 res.status() 被调用并带有 200 状态代码。

它不会测试res.status() 是否被调用。例如,如果我从 controller.js 中删除行 res.status(200).send();,测试仍然通过。

我尝试在res.status 上创建spy。它没有按预期工作。

【问题讨论】:

    标签: node.js unit-testing mocha.js sinon chai


    【解决方案1】:

    问题是您的代码没有指示异步函数何时完成。虽然我们可以在测试中添加一个计时器来解决这个问题,但这是一个有点垃圾的解决方案。

    以一种很好的方式解决这个问题的最简单方法是从你的函数中返回承诺:

    return User.findOne({ _id: userId })
           ....
    

    在此之后,在您的测试中,您可以简单地执行以下操作:

    return controller.getUserById(validReqObj, validRes).then(function() {
        mock.restore();
        mock.verify();
    });
    

    还要注意测试中的返回 - 这允许 mocha 检测到它是一个带有承诺的异步测试。

    【讨论】:

      【解决方案2】:

      这是因为getUserById 是异步函数。即使您为 User 模型创建了模拟,getUserById 仍然是异步的。

      要创建正确的测试,您可以执行以下操作:

      • getUserById 函数返回promise 并创建它测试的promise 链。
      • 使用supertest模块发送真实的http请求并验证响应。

      【讨论】:

        猜你喜欢
        • 2015-12-01
        • 2017-10-08
        • 2016-05-26
        • 1970-01-01
        • 2023-03-22
        • 1970-01-01
        • 1970-01-01
        • 2015-07-25
        • 2015-10-01
        相关资源
        最近更新 更多