【问题标题】:Mocking Http Post Request using Jest in NodeJs在 NodeJs 中使用 Jest 模拟 Http Post 请求
【发布时间】:2021-11-09 09:37:35
【问题描述】:

我有一个使用本机 https.request 在 Azure Function 中使用 Node J 构建的外部 POST API,一切正常。现在我正在尝试构建单元测试用例并被模拟请求方法所吸引。

回调响应具有“on”功能,需要根据“data”或“end”值进行模拟。

我收到此错误 TypeError: res.on is not a function

以下是代码。任何建议!

index.js

'use strict';
const https = require('https')
const fs = require('fs')
const path = require('path')

module.exports = function(context, postData) {
    //Accessing Certificate and Passing along with Request Options for SSL Handshake
    var ca_path = path.join(__dirname, 'my_cert.cer');
    https.globalAgent.options.ca = fs.readFileSync(ca_path).toString()
        .split(/-----END CERTIFICATE-----\n?/)
        // may include an extra empty string at the end
        .filter(function(cert) { return cert !== ''; })
        // effectively split after delimiter by adding it back
        .map(function(cert) { return cert + '-----END CERTIFICATE-----\n'; });

    let auth = 'Basic ' + Buffer.from(process.env.username + ':' + process.env.pwd).toString('base64');

    let post_option = {
        host: process.env.host,
        path: process.env.path,
        method: 'POST',
        port: process.env.port,
        headers: {
            'Content-Type': 'application/json',
            'Authorization': auth,
            'X-Correlation-ID': JSON.parse(postData).correlationId
        }
    };

    return new Promise(function(resolve, reject) {
        var req = https.request(post_option, function(res) {
            // accumulate data
            var body = [];
            res.on('data', function(chunk) { //here is the type error
                body.push(chunk);
            });
            // resolve on end
            res.on('end', function() {
                context.log("API status: " + res.statusCode);
                if (res.statusCode == 200) {
                    try {
                        body = JSON.parse(Buffer.concat(body).toString());
                        context.log("API Success: ");
                    } catch (err) {
                        reject(err);
                    }
                    resolve(body);
                } else if (res.statusCode == 401) {
                    let errJson = {};
                    context.log("API authentication error...");
                    let err = new Error();
                    errJson["errorCode"] = res.statusCode;
                    errJson["errorMessage"] = res.statusMessage;
                    errJson["errorDescription"] = res.statusMessage;
                    err = errJson;
                    return reject(err);
                } else {
                    body = JSON.parse(Buffer.concat(body).toString());
                    context.log("API error...", body);
                    let err = new Error();

                    if (body.error != null && body.error != undefined) {
                        err = body.error;
                    } else {
                        let errJson = {};
                        errJson["errorCode"] = res.statusCode;
                        errJson["errorMessage"] = res.statusMessage;
                        errJson["errorDescription"] = res.statusMessage;
                        err = errJson;
                    }
                    return reject(err);
                }
            });
        });
        // reject on request error
        req.on('error', function(err) {
            context.log("API Generic error...", err);
            let err = new Error();
            let errJson = {};
            if (err.message && err.message.indexOf("ENOTFOUND") >= 0)
                errJson["errorCode"] = 404;
            else
                errJson["errorCode"] = 500;
            errJson["errorMessage"] = err.message;
            errJson["errorDescription"] = err.message;
            err = errJson;
            reject(err);
        });
        if (postData) {
            req.write(postData);
        }
        req.end();
    });
}

index.test.js

 var https = require('https');
    jest.mock('https', () => ({
    ...jest.requireActual('https'), // import and retain the original functionalities
    request: (post_option, cb) => cb('res')({
         on: jest.fn()
    }),
    on: jest.fn(),
    write: jest.fn(),
    end: jest.fn()
}));


 /*
jest.mock('https', () => ({
...jest.requireActual('https'), // import and retain the original functionalities
request: (post_option, cb) => cb('res')({
    on: (data, cb) => cb('data')
}),
on: jest.fn(),
write: jest.fn(),
end: jest.fn()
}));
*/

/*    jest.mock('https', () => ({
      ...jest.requireActual('https'), // import and retain the original functionalities
      request: (post_option, cb) => cb(jest.fn(() => ({
        on: jest.fn()
      }))),
      on: jest.fn(),
      write: jest.fn(),
      end: jest.fn()
      })); 
*/

/*  jest.mock('https', () => ({
    ...jest.requireActual('https'), // import and retain the original functionalities
    request: (post_option, cb) => cb({
     on: jest.fn()
    })
    })); 
*/

尝试了不同的方法来为“on”函数创建模拟,但没有成功。

【问题讨论】:

    标签: javascript node.js unit-testing jestjs mocking


    【解决方案1】:

    经过 3 个小时的实验,终于可以模拟 'res' 的 'on' 功能了。

    cb 实际上应该设置为需要 2 个参数的函数

    这是模拟语法。

    let apiResponseBody = `{
                             "status": "Dummy Request sent to API"
                           }`;
        
    var https = require('https');
    jest.mock('https', () => ({
     ...jest.requireActual('https'), // import and retain the original functionalities
     request: (post_option, cb) => cb({
      on: (data, cb) => cb(Buffer.from(apiResponseBody, 'utf8')),
      statusCode: 200,
      statusMessage: 'API Success'
     }),
     on: jest.fn(),
     write: jest.fn(),
     end: jest.fn()
    }));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-09
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-24
      相关资源
      最近更新 更多