首页 > 解决方案 > 如何在 JEST 中模拟繁琐的模块 SQL 连接函数

问题描述

我正在使用用 Nodejs 编写的 Azure 函数。

在所有操作完成后,我有逻辑插入数据库。这在一些 api 调用后从主 index.js 调用。所以,从测试类我期待模拟数据库方法。并且不能理解嘲笑!

下面是数据库逻辑的代码。

'use strict';
const { Connection, Request, TYPES } = require('tedious');
const config = {
    server: process.env.myDB_Server,
    authentication: {
        type: 'default',
        options: {
            userName: process.env.myDB_User,
            password: process.env.myDB_Pwd
        }
    },
    options: {
        encrypt: true,
        database: process.env.myDB_Name
    }
};
const myDB = process.env.myDB;
module.exports = async(context, myPayload, last_Modified_By, status, errorCode, errorMsg, errorDescription) => {
    try {
        context.log('inside azureTable function');
        let connection = new Connection(config);
        connection.on('connect', function(err1) {
            if (err1) {
                context.log('Error connection.OnConnect to DB:::', err1.message);
                //logger.error('Error connection.OnConnect to DB::', err1);
                let dbStatus = {};
                dbStatus["status"] = 400;
                dbStatus["message"] = err1.message;
                context.res.body["dbStatus"] = dbStatus;
                context.done();
            } else {
                context.log('Database Connection Successful.');
                var request = new Request("INSERT INTO  " + myDB + " (Correlation_Id,Created_Date,LastModified_Date,Last_Modified_By,Status_CD,Error_Code,Error_Msg,Error_Description,Payload)  VALUES (@correlationId,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,@Last_Modified_By,@Status_CD,@Error_Code,@Error_Msg,@Error_Description,@Payload);", function(err2) {
                    if (err2) {
                        context.log('Error inserting records to DB::', err2.message);
                        //logger.error('Error inserting records to DB::' + err2.message);
                        let dbStatus = {};
                        dbStatus["status"] = 400;
                        dbStatus["message"] = err2.message;
                        context.res.body["dbStatus"] = dbStatus;
                        context.done();
                    }
                });
                request.addParameter('correlationId', TYPES.NVarChar, JSON.parse(myPayload).correlationId);
                request.addParameter('Last_Modified_By', TYPES.NVarChar, last_Modified_By);
                request.addParameter('Status_CD', TYPES.NVarChar, status);
                request.addParameter('Error_Code', TYPES.Int, errorCode);
                request.addParameter('Error_Msg', TYPES.NVarChar, errorMsg);
                request.addParameter('Error_Description', TYPES.NVarChar, errorDescription);
                request.addParameter('Payload', TYPES.NVarChar, myPayload);
               
                // Close the connection after the final event emitted by the request, after the callback passes
                request.on("requestCompleted", function(rowCount, more) {
                    context.log('Records Successfully inserted into DB');
                    connection.close();
                    let dbStatus = {};
                    dbStatus["status"] = 201;
                    dbStatus["message"] = "Records Successfully inserted into DB";
                    context.res.body["dbStatus"] = dbStatus;
                    context.done();
                });
                connection.execSql(request);
            }
        });
        connection.connect();
    } catch (err) {
        context.log('Error  in main function::', err.message);
        //logger.error('Error  in main function::' + err.message);
        let dbStatus = {};
        dbStatus["status"] = 400;
        dbStatus["message"] = err.message;
        context.res.body["dbStatus"] = dbStatus;
        context.done();
    }
};

我如何模拟 connection.on 连接或请求 = 新请求而不实际命中数据库?

我试过这个,但它会实际连接。

index.test.js

 test('return 500 when db connection fails" ', async() => {
     const tedious = require('tedious');
            const connectionMock = jest.spyOn(tedious, 'connect');
            connectionMock.mockImplementation(() => {
                return {
    
                }
            });
            //calling index js
 }, 15000);

test('return 500 when db connection fails" ', async() => {
         const tedious = require('tedious');
                const connectionMock = jest.spyOn(tedious, 'Connection');
                connectionMock.mockImplementation(() => {
                     {
                       throw new Error('some err');
                    }
                });
            //calling index js
     }, 15000);

在浏览了一些文档后,在下面尝试但没有运气。Jest 没有设置返回值并超时。

jest.mock('tedious', () => ({
Connection: jest.fn(() => ({
  connect: jest.fn().mockReturnValue('err'),
  on: jest.fn().mockReturnValue('err')
  }))
}))  

 /* jest.mock('tedious', () => ({
   Connection: jest.fn(() => ({
     connect: jest.fn(() => (connect, cb) => cb(null)),
     on: jest.fn(() => (connect, cb) => cb('err'))
     }))
   })) */

标签: jestjsmockingdatabase-connection

解决方案


最后我想通了。问题是没有正确设置模拟参数。不必要地将 Jest.fn() 用于实际上没有帮助的内部方法。

这是最终的解决方案:

jest.mock('tedious', () => ({
     Connection: jest.fn(() => ({
                connect: () => {},
                on: (connect, cb) => cb(),
                close: () => {},
                execSql: () => {}
     })),
     TYPES: jest.fn(),
     Request: jest.fn(() => ({
                constructor: (sqlString, cb) => cb('err', null, null),
                addParameter: (name, type, value) => {},
                on: (requestCompleted, cb) => cb('rowCount', 'more')
     }))
  }))

推荐阅读