我有以下实现。如何进行单元测试。我想确保processData
仅在成功时调用一次,而handleDecryptError
在错误时调用一次。
我的单元测试抛出一个错误,指出AssertionError: expected 0 to equal 1
的{{1}}。
实施:
should.equal(getHandleDecryptErrorSpy.callCount, 1);
测试用例:
let getData = exports.getData = (err, res, param) => {
...
return security.decryptJWE(jweParts[0], jweParts[1], jweParts[2], jweParts[3], jweParts[4], privatekey)
.then(data => processData(data, param))
.catch(error => handleDecryptError(error, param));
}
let handleDecryptError = exports.handleDecryptError = (error, param) => {
log.error(message.ERROR_DECRYPTING.red, error);
..
return;
}
let processData = exports.processData = (momData, param) => {
log.info(message.SUCCESS.red);
...
}
答案 0 :(得分:0)
如果您从updateTask.getData
返回了承诺,则可以在测试中将其调用,并将断言放在该调用所附的then()
中。现在,测试可以等待getData()
解决,然后再尝试任何断言:
it('6. Response for data is empty string', () => { // don't pass done
return updateTask.getData() // return this promise and mocha will handle it
.then(() => {
// assertions will now run at the right time
should.equal( /* etc */)
}
此外,如果您未通过done
,则可以返回测试中的承诺,摩卡咖啡就会知道测试何时结束。
此外,由于您使用的是Sinon — Sinon有一个不错的assertion library,您可以像这样使用:sinon.assert.calledOnce(getDecryptJWESpy);
。这将为您提供有关equal
失败的更好消息。
答案 1 :(得分:0)
我认为您要做的就是等待诺言。使用async/await
更容易:
it('6. Response for data is empty string', async () => {
let getDecryptJWESpy = sinon.stub(security, "decryptJWE").resolves(message.ERROR_DECRYPTING);
let getProcessDataSpy = sinon.spy(updateTask, "processData");
let getHandleDecryptErrorSpy = sinon.spy(updateTask, "handleDecryptError");
let response = {
body: "",
text: ""
};
try {
await updateTask.getData(null, response, ["TASKID"]);
} catch(ignore) {}
should.equal(getDecryptJWESpy.callCount, 1);
should.equal(getProcessDataSpy.callCount, 0);
should.equal(getHandleDecryptErrorSpy.callCount, 1);
});
答案 2 :(得分:0)
您首先需要确定需要测试的内容以及测试用例的完成时间。同样,由于您的代码使用回调而不是异步等待,因此使用done()声明结果更容易。
成功后,通过必要的参数测试一次processData仅被调用
调用processData时成功测试完成
因此您的测试用例变为
it('6. Response for data is empty string', (done) => {
let getDecryptJWESpy = sinon.stub(security, "decryptJWE").resolves(message.ERROR_DECRYPTING);
let getHandleDecryptErrorSpy = sinon.stub(updateTask, "handleDecryptError");
let getProcessDataSpy = sinon.stub(updateTask, "processData").callsFake(function fakeFn() {
should.equal(getDecryptJWESpy.callCount, 1);
should.equal(getProcessDataSpy.callCount, 1);
should.equal(getHandleDecryptErrorSpy.callCount, 0);
//The test is done only is this point is reached
done();
});
let response = {
body: "",
text: ""
};
updateTask.getData(null, response, ["TASKID"]);
});
失败时,请测试是否仅使用必需的参数调用一次handleDecryptError
调用handleDecryptError时失败测试完成
因此您的测试用例变为
it('6. Response for data is empty string', (done) => {
let getDecryptJWESpy = sinon.stub(security, "decryptJWE").resolves(message.ERROR_DECRYPTING);
let getProcessDataSpy = sinon.stub(updateTask, "processData");
let getHandleDecryptErrorSpy = sinon.stub(updateTask, "handleDecryptError").callsFake(function fakeFn() {
should.equal(getDecryptJWESpy.callCount, 1);
should.equal(getProcessDataSpy.callCount, 0);
should.equal(getHandleDecryptErrorSpy.callCount, 1);
//The test is done only is this point is reached
done();
});
let response = {
body: "",
text: ""
};
updateTask.getData(null, response, ["TASKID"]);
});
按原样的代码可能无法正常工作,因为我尚未对其进行测试,但是根据我的说法,测试的结构应如上所述。
答案 3 :(得分:0)
我的第一个建议是在所有地方使用回调或Promise保持一致。由于security.decryptJWE
使用诺言,因此我们将使getData
也使用诺言。
let getData = exports.getData = (err, res, param) => {
...
// add 'return' so `getData` returns promise
return security.decryptJWE(jweParts[0], jweParts[1], jweParts[2], jweParts[3], jweParts[4], privatekey)
.then(data => processData(data, param))
.catch(error => handleDecryptError(error, param));
}
似乎您的测试用例想要测试是否调用handleDecryptError
,因此您必须使用rejects
而不是resolves
。如果使用resolves
,它将转到processData
而不是handleDecryptError
。
it('6. Response for data is empty string', () => {
let getDecryptJWESpy = sinon.stub(security, "decryptJWE").rejects(message.ERROR_DECRYPTING); // update to use rejects
let getProcessDataSpy = sinon.spy(updateTask, "processData");
let getHandleDecryptErrorSpy = sinon.spy(updateTask, "handleDecryptError");
let response = {
body: "",
text: ""
};
return updateTask.getData(null, response, ["TASKID"]) // add 'return' and 'then'
.then(() => { // alternatively, we can use `async/await`
should.equal(getDecryptJWESpy.callCount, 1);
should.equal(getProcessDataSpy.callCount, 0);
should.equal(getHandleDecryptErrorSpy.callCount, 1);
});
});
希望有帮助