如何在 JEST 中模拟乏味模块 SQL 连接函数

How to mock Tedious Module SQL Connection functions in JEST

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

我有在所有操作完成后插入数据库的逻辑。在一些 api 调用之后,它从 main index.js 调用。因此,从测试 class 我希望模拟数据库方法。并且无法理解嘲笑!

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

'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 connect 或 request = new Request 而不实际访问 DB?

我试过了,但它会进入实际连接。

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 未设置 return 值并超时。

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'))
     }))
   })) */

我终于明白了。 问题是没有正确设置模拟参数。不必要地使用 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')
     }))
  }))