【问题标题】:How to mock node database connection in unit tests?如何在单元测试中模拟节点数据库连接?
【发布时间】:2020-10-15 07:15:23
【问题描述】:

我正在为 Node.js node-oracledb 使用 Oracle 数据库驱动程序。我做了一些研究,但找不到任何关于如何对数据库连接进行单元测试的明确解决方案。我应该连接到真实数据库还是模拟连接。哪个框架适合模拟数据库连接?我想对依赖于 oracledb 的发布请求 /API/login 进行单元测试。下面分享代码。请指导。

var express = require('express');
var router = express.Router();
var oracledb = require('oracledb');
var jwt = require('jsonwebtoken');
var database = {};

router.use('/', function postLogins(req, res) {

  database.user = req.body.email.toUpperCase();
  database.password = req.body.password;
  database.connectString = process.env.DB_HOST;

  oracledb.getConnection(
    database,
    function connectToDatabase(connectionError, connection) {
      var payload;

      if (connectionError) {
        res.set('Content-Type', 'application/json');
        res.status(500).send(JSON.stringify({
          status: 500,
          message: 'Error connecting to DB',
          detailed_message: connectionError.message
        }));
        return;
      }

      payload = {
        sub: req.body.email
      };

      res.status(200).json({
        user: req.body.email,
        token: jwt.sign(payload, process.env.SECRET_KEY, { expiresIn: '8h' })
      });

      connection.release(function onRelease(releaseError) {
        if (releaseError) {
          console.error(releaseError.message);
        } else {
          console.log('POST /logins : Connection released');
        }
      });
    }
  );
});

module.exports = router;

【问题讨论】:

    标签: node.js unit-testing node-oracledb


    【解决方案1】:

    我应该连接到真实的数据库还是模拟连接。

    这实际上取决于您的测试范围。 Oracle 是您无法控制且必须与之交互的依赖项。只要这段代码在某个时候被执行,它就会被测试,也许是由客户端,但希望在它到达客户端之前。我认为这两种方法都很有价值。

    哪个框架适合模拟数据库连接?

    我会尝试使用某种设计模式来隔离您的依赖关系并提高可测试性。高度嵌套的匿名函数使您难以隔离部分代码,几乎需要您在粗略的级别上运行您的处理程序。有几个选项可以帮助分解您的处理程序并使其在单元级别上更具可测试性。我认为第一步可能是提取您的处理程序:

    class PostLogins {
       constructor(db) {
         this.db = db || oracledb;
       }
    
       handle(req, res) {
         // use this.db
       }
    }
    
    var pl = new PostLogins();
    router.use('/', pl.handle);
    

    这将允许您直接运行您的处理程序,但当然不会测试它是否已连接到您的框架中。它还允许您为单元测试提供 oracle 的存根实现,以验证处理程序的流程是否正常工作。即使使用存根 oracle 进行单元测试,您也将丢失对实际 oracle 交互和 http 交互的覆盖。另一个有助于可测试性的重构是拆分connectToDatabase

    根据您的项目的成熟度,首先创建一个粗粒度的高级测试来启动 oracle,启动您的网络服务器,然后运行您的端点并验证是否已收到成功的响应,这可能是有意义的。如果它在您的项目生命周期的早期并且实现仍在更改,或者如果您的项目已经发布给客户端,我会选择这种方法,以允许您更改实现和重构并且仍然具有 HTTP 和成功请求的测试覆盖率没有退步。

    【讨论】:

    • 感谢您的快速回复。根据您的回复,我将着手重构我的代码。此外,我还使用 Nightwatch 框架对全部功能进行了端到端测试。
    猜你喜欢
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    相关资源
    最近更新 更多