我正在开发Node.js应用程序。
这是validate.js文件的代码,我在其中定义了一个类Validate和静态方法validateTicket,并在底部导出了该类。
const request = require("request");
const config = { urlBase: "" };
class Validate {
static validateTicket = (ticket) => {
const options = { url: config.urlBase + ticket, json: true, rejectUnauthorized: false };
return new Promise((resolve, reject) => {
request.get(options, (error, response, body) => {
if (error) {
reject(error);
return;
}
if (response) {
resolve(response);
return;
}
reject(null);
});
});
};
}
module.exports = Validate;
这是我要导入validate.js文件的主要实用程序文件,并且有3个函数validateTicketReqs
,to_json
和sendErrorResponse
。
[validateTicketReqs
函数对从类方法收到的响应进行验证。
const validate = require('./validate.js');
function validateTicketReqs(req, res, next, flag, num) {
let payload = req.body;
let ticket= (payload.ticket) ? payload.ticket: null;
let error_msg = 'Failed to obtain a successful response '
validate.validateTicket(ticket).then(
(resolution) => {
let json = to_json(resolution); // function will return null value for json
if (json === null || !('body' in json)) {
return sendErrorResponse(req, res, 500, 'error');
}
...
})
function sendErrorResponse(req, res, code, msg) {
let resBody = {
msg: msg
};
res.status(code);
res.send(resBody);
}
const validate = require('./validate.js');
describe("Check", () => {
it("should fail due to error", (done) => {
let req = {
authData: {'user_id': "mock"},
body: {"num": "mock", "tikcet": "mock"},
request_id: 'mock'
};
let res = {send: sinon.spy(), status: sinon.spy()};
let next = sinon.spy();
mock_buffer = {
toJSON : function() { return {body: {environment: 'mock', status: 'mock'}}},
statusCode: 500
}
const validateTicket= sinon.stub(validate, 'validateTicket')
validateTicket.resolves(mock_buffer)
util.valdateTicketReqs(req, res, next, flag, "mock" );
expect(res.send.calledOnce).to.be.true; ##not getting called
expect(res.send.firstCall.args[0].statusCode).to.equal(500); ##not getting called
util.valdateTicketReqs.restore();
validate.validateTicket.restore();
done();
});
});
我面临的问题是(res.send.calledOnce)
值即将变为假。我期望res.send()
应该至少被调用一次,但不是。请在这里告知问题所在。让我知道您是否对此问题有疑问。
问题是在测试用例完成之前调用了expect
方法。您的validate.validateTicket
方法的返回值是一个promise,它是异步方法。您需要将其返回,以便测试运行程序知道测试用例是否完成。
例如
validate.ts
:
const request = require("request");
const config = { urlBase: "" };
class Validate {
static validateTicket = (ticket) => {
const options = { url: config.urlBase + ticket, json: true, rejectUnauthorized: false };
return new Promise((resolve, reject) => {
request.get(options, (error, response, body) => {
if (error) {
reject(error);
return;
}
if (response) {
resolve(response);
return;
}
reject(null);
});
});
};
}
module.exports = Validate;
util.ts
:
const validate = require("./validate");
function to_json(data) {
return null;
}
function sendErrorResponse(req, res, code, msg) {
const resBody = {
msg: msg,
};
res.status(code);
res.send(resBody);
}
export function validateTicketReqs(req, res, next, flag, num) {
const payload = req.body;
const ticket = payload.ticket ? payload.ticket : null;
const error_msg = "Failed to obtain a successful response ";
return validate.validateTicket(ticket).then((resolution) => {
const json = to_json(resolution);
if (json === null || !("body" in json)) {
return sendErrorResponse(req, res, 500, "error");
}
});
}
util.spec.ts
:
import sinon from "sinon";
import { expect } from "chai";
import * as util from "./util";
const validate = require("./validate");
describe("Check", () => {
it("should fail due to error", async () => {
const req = {
authData: { user_id: "mock" },
body: { num: "mock", tikcet: "mock" },
request_id: "mock",
};
const res = {
send: sinon.spy(),
status: sinon.spy(),
};
const next = sinon.spy();
const flag = "";
const mock_buffer = {
toJSON: function() {
return { body: { environment: "mock", status: "mock" } };
},
statusCode: 500,
};
const validateTicketStub = sinon.stub(validate, "validateTicket").resolves(mock_buffer);
await util.validateTicketReqs(req, res, next, flag, "mock");
expect(res.send.calledOnce).to.be.true;
expect(res.status.firstCall.args[0]).to.equal(500);
sinon.assert.calledOnce(validateTicketStub);
validateTicketStub.restore();
});
});
带有覆盖率报告的单元测试结果:
Check
✓ should fail due to error
1 passing (19ms)
--------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
--------------|----------|----------|----------|----------|-------------------|
All files | 76.09 | 30 | 63.64 | 75.56 | |
util.spec.ts | 94.12 | 100 | 66.67 | 93.75 | 22 |
util.ts | 100 | 50 | 100 | 100 | 9,14 |
validate.ts | 37.5 | 0 | 25 | 37.5 |... 12,15,16,17,20 |
--------------|----------|----------|----------|----------|-------------------|
源代码:https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/59037819