在 NodeJs 中使用 Jest 模拟 Http Post 请求
Mocking Http Post Request using Jest in NodeJs
我有一个外部 POST API 使用原生 https.request 使用 Azure Function 中的 Node Js 构建,一切正常。现在我正在尝试构建单元测试用例并且对模拟 Request 方法感到震惊。
回调响应具有 'on' 函数,需要根据值 'data' 或 'end' 进行模拟。
我收到此错误 类型错误:res.on 不是函数
下面是代码。任何建议!
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' 函数创建模拟但没有成功。
经过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()
}));
我有一个外部 POST API 使用原生 https.request 使用 Azure Function 中的 Node Js 构建,一切正常。现在我正在尝试构建单元测试用例并且对模拟 Request 方法感到震惊。
回调响应具有 'on' 函数,需要根据值 'data' 或 'end' 进行模拟。
我收到此错误 类型错误:res.on 不是函数
下面是代码。任何建议!
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' 函数创建模拟但没有成功。
经过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()
}));