首页 > 解决方案 > 大多数 RESTFUL API 函数无法进行单元测试

问题描述

postAdmin(req, res, cb) {
    const admin = await Admin.findOne({ req.body.username });

    if (!admin) {
        error("Admin doesn't exist");
    } //split here? adminValidationDAO();

    const isMatch = await bcrypt.compare(password, user.password);

    if(!isMatch){
        error("Wrong password");
    } //split here? passwordValidationDAO();
    const email = new Email ({
        text: req.body.text,
        title: req.body.title,
    });
    const response = await email.save();
    //split here? saveResponseDAO()?
}

单元测试是测试小段代码的实践,通常是单独的功能,单独和隔离。如果您的测试使用一些外部资源,例如网络或数据库,则它不是单元测试。

我正在考虑测试我上面的代码,但是在对单元测试进行了一些研究之后,我意识到我认为单元测试是集成测试。在 postAdmin 中测试整个代码块将是集成测试。然后我想知道我是否可以将 postAdmin 中的代码分成三个块并使它们可单元测试,但这里有以下问题:

第一个使用 findOne() 进行数据库调用。

第二个依赖图书馆,那不是外部资源吗?

第三个使用 save() 进行数据库调用。

那么您是否同意没有什么可以进行单元测试?

标签: node.jsunit-testingtdd

解决方案


您肯定想测试边缘情况,例如查询失败或返回 null 时引发的错误。您应该尝试使用覆盖工具来帮助您确定所有分支(路径)都包含在您的单元测试中。一个伟大且常用的工具是伊斯坦布尔。通过这样做,您可以了解测试执行了哪些语句(您应该以 100% 为目标,尽管这有点不可能)。您可以使用模拟框架来模拟外部依赖项并驱动它们的行为,以便您可以专注于您的功能。

例如,我会模拟Admin.findOne({req.body.username });返回 null,并测试是否引发了错误。

我会为它做同样的事情bcrypt.compare(password, user.password);并让它返回false,这样我就可以测试是否抛出了错误。这样做,您将拥有一套测试,允许您重构函数而不必担心改变行为。


推荐阅读