简体   繁体   English

如何在单元测试中模拟节点数据库连接?

[英]How to mock node database connection in unit tests?

I am using Oracle Database driver for Node.js node-oracledb.我正在为 Node.js node-oracledb 使用 Oracle 数据库驱动程序。 I did some research and not able to find any clear solution on how to unit test DB connection.我做了一些研究,但找不到任何关于如何对数据库连接进行单元测试的明确解决方案。 Should I connect to the real database or mock the connection.我应该连接到真实的数据库还是模拟连接。 Which framework will be good for mocking DB connection?哪个框架适合模拟数据库连接? I want to unit test post request /API/login which depend on oracledb.我想对依赖于 oracledb 的 post request /API/login 进行单元测试。 Sharing the code below.分享下面的代码。 Please guide.请指导。

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;

Should I connect to the real database or mock the connection.我应该连接到真实的数据库还是模拟连接。

It really depends on the scope of your test.这实际上取决于您的测试范围。 Oracle is a dependency that you don't control and must interact with. Oracle 是一个您无法控制且必须与之交互的依赖项。 As long as this code is executed at some point it will be tested, maybe by a client, but hopefully before it reaches the client.只要这段代码在某个时候被执行,它就会被测试,可能是由客户端测试,但希望在它到达客户端之前。 I think that both approaches are valuable.我认为这两种方法都很有价值。

Which framework will be good for mocking DB connection?哪个框架适合模拟数据库连接?

I would try and use some sort of design patterns to isolate your dependencies and increase testability.我会尝试使用某种设计模式来隔离您的依赖项并提高可测试性。 The highly nested anonymous functions make it difficult to isolate parts of your code, almost requiring you to exercise your handler at a coarse level.高度嵌套的匿名函数使隔离部分代码变得困难,几乎需要您在粗略的级别上练习处理程序。 There are a couple options that could help to break apart your handler and make it more testable at a unit level.有几个选项可以帮助拆分处理程序并使其在单元级别更易于测试。 I think the first step could be to extract your handler:我认为第一步可能是提取您的处理程序:

class PostLogins {
   constructor(db) {
     this.db = db || oracledb;
   }

   handle(req, res) {
     // use this.db
   }
}

var pl = new PostLogins();
router.use('/', pl.handle);

This will allow you to exercise your handler directly, but of course will not test that it is wired into your framework.这将允许您直接运行您的处理程序,但当然不会测试它是否已连接到您的框架中。 It also allows you to provide a stub implementation of oracle for your unit test, to verify that the flow of your handler works correctly.它还允许您为单元测试提供 oracle 的存根实现,以验证处理程序的流程是否正常工作。 Even with a unit test using a stub oracle you will be missing coverage on your actual oracle interactions, and your http interactions.即使使用存根 oracle 进行单元测试,您也会缺少对实际 oracle 交互和 http 交互的覆盖。 Another refactor that would help with testability is to break out connectToDatabase .另一个有助于可测试性的重构是打破connectToDatabase

Depending on the maturity of your project it might make sense to first create a coarse-grained high level test that starts up oracle, starts up your webserver and then exercises your endpoint and verifies that the successful response has been received.根据您项目的成熟度,首先创建一个粗粒度的高级测试来启动 oracle,启动您的网络服务器,然后运行您的端点并验证是否已收到成功响应可能是有意义的。 I would opt for this approach if it is very early in your projects lifecycle and implementations are still changing OR if your project has already been release to clients, to allow you to change the implementations and refactor and still have test coverage that HTTP and successful requests haven't regressed.如果您的项目生命周期很早并且实现仍在更改,或者如果您的项目已经发布给客户,我会选择这种方法,以允许您更改实现和重构并且仍然具有 HTTP 和成功请求的测试覆盖率没有退步。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM