【问题标题】:unit test fails even though the code works即使代码有效,单元测试也会失败
【发布时间】:2022-11-06 17:57:12
【问题描述】:

即使代码有效,用于测试登录控制器的单元测试也会失败。 如果访问数据库失败,我需要测试是否写入状态代码 500。 我使用 sinon 包来模拟 findOne mongoose 的功能。

测试代码:

describe("Auth Controller - Login", function () {
    it("should throw an error with code 500 if accessing the database fails", function (done) {
        sinon.stub(User, "findOne");
        User.findOne.throws();

        const req = {
            body: {
                email: "test@test.com",
                password: "test123",
            },
        };

        authController
            .postLogin(req, {}, () => {})
            .then((result) => {
                expect(result).to.be.an("error");
                expect(result).to.have.property("httpStatusCode", 500);
                done();
            });

        User.findOne.restore();
    });
});

控制器:

exports.postLogin = (req, res, next) => {
    const email = req.body.email;
    const password = req.body.password;

    const errors = validationResult(req);
    if (!errors.isEmpty()) {
        return res.status(422).json({ error: errors.array()[0].msg });
    }

    User.findOne({ email: email })
        .then((user) => {
            if (!user) {
                return res.status(401).json({ error: "User does not exist!" });
            }
            bcrypt
                .compare(password, user.password)
                .then((doMatch) => {
                    if (doMatch) {
                        const token = jwt.sign(
                            { email: email, userId: user._id },
                            process.env.SESSION_SECRET,
                            {
                                expiresIn: "3d",
                            }
                        );
                        return res.status(200).json({
                            token: token,
                            userId: user._id.toString(),
                            email: email,
                        });
                    }
                    return res.status(401).json({ error: "Invalid Password!" });
                })
                .catch((err) => {
                    throw new Error(err);
                });
        })
        .catch((err) => {
            const error = new Error(err);
            error.httpStatusCode = 500;
            next(error);
            return error;
        });
};

当 findOne 抛出错误(由 sinon 触发)时,catch 块应该返回带有 500 代码的错误。但运行此测试失败。

1 failing

  1) Auth Controller - Login
       should throw an error with code 500 if accessing the database fails:
     Error
   Error
      at Object.fake.exceptionCreator (node_modules/sinon/lib/sinon/default-behaviors.js:24:20)
      at Object.invoke (node_modules/sinon/lib/sinon/behavior.js:165:35)
      at Function.functionStub (node_modules/sinon/lib/sinon/stub.js:42:43)
      at Function.invoke (node_modules/sinon/lib/sinon/proxy-invoke.js:50:47)
      at Function.findOne (node_modules/sinon/lib/sinon/proxy.js:285:26)
      at Object.exports.postLogin (controllers/auth.js:68:7)
      at Context.<anonymous> (test/auth-controller.js:19:5)
      at processImmediate (internal/timers.js:464:21)

【问题讨论】:

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


    【解决方案1】:

    首先,您需要使用 before 钩子连接数据库,如下所示:

    before(async () => {
      await mongoose.connect(databaseUrl);
    });
    

    并清理您的数据库并使用钩子后断开它:

    after( async () => {
      await mongoose.disconnect();
    });
    

    我建议您不要在测试中使用 done 而是使用 async-await 因为您使用的是 async-await,所以您不再需要使用 done 方法,并且您可以避免很多不必要的复杂性。

    【讨论】:

    • 我不需要连接到数据库,因为我已经使用 sinon 模拟了 findOne 函数。该函数只是使用示例用户模拟 findOne。
    • 您可以在 Replit 上上传您的代码,以便我们对其进行测试,看看有什么问题吗?
    猜你喜欢
    • 2016-06-23
    • 2014-09-18
    • 2010-11-19
    • 2023-03-27
    • 1970-01-01
    • 2017-10-31
    • 2018-12-17
    • 1970-01-01
    • 2014-09-07
    相关资源
    最近更新 更多