JS里面异步非常普遍,后端开发就免不了对异步函数进行单元测试(UT)了。
那么怎么测试then, tap,catch后面的路径呢? 看例子
案例分析
代码
有如下方法updateStateExceptAxc需要写单元测试, 存放在文件名为radioStateHelper.js里。
// radioStateHelper.js
function updateStateExceptAxc(antennaLineUri) {
// 代码...
return module.exports.updateState(affectedUrisExceptAxc)
.tap(function() {
logger.debug("change state of resource %s successful", JSON.stringify(affectedUrisExceptAxc));
}).catch(function(err) {
logger.error("change state of resource %s failed, fail reason %s", JSON.stringify(affectedUrisExceptAxc), err.message);
});
}
function updateState(resourceUris) {
return Promise.try(function() {
resourceUris.forEach(function(resourceUri) {
var availabilityStatus = module.exports.getWorstStatus(resourceUri);
var status = {
availabilityStatus: availabilityStatus,
operationalState: (availabilityStatus === availabilityStatus.FAILED ||
availabilityStatus === availabilityStatus.OFFLINE) ? operationalState.DISABLED : operationalState.ENABLED
};
mzframe.updateResourceByUri(resourceUri, status);
});
});
}
// only for UT testing
module.exports.updateStateExceptAxc = updateStateExceptAxc;
module.exports.updateState = updateState;
单元测试文件,对updateStateExceptAxc()方法进行测试。
it.only("updateStateExceptAxc(): should call updateState method once", function(done) {
inq.mock(radioStateHelper, "updateState"); // 注意这里,有问题需要改进
inq.expect(radioStateHelper.updateState).once;
radioStateHelper.updateStateExceptAxc(antennaLineUri).then(done);
});
测试结果
不能够找到undefined的tap
分析
期望结果
首先测试里,我们mock了一个updateState
方法,并且期望当调用radioStateHelper.updateStateExceptAxc(antennaLineUri)
时候,这个mock的方法被执行一次【().once
】。
实际情况
抛出了异常(TypeError: Cannot read property ‘tap’ of undefined)。
原因分析
其实,mock的updateState方法是被执行了一次,只是这里的错误是由于module.exports.updateState(affectedUrisExceptAxc).tap(function()
的tap
引起的,这里期望module.exports.updateState(affectedUrisExceptAxc)
返回的是一个异步内容,能够thenable的。 所以需要在mock的时候,返回一个thenable内容。
改进措施
// 代码更改
inq.mock(radioStateHelper, "updateState"); // 注意这里,有问题需要改进
// ==> 更改 ==>
// 如果测试tap路径
inq.mock(radioStateHelper, "updateState").returns(Promise.resolve());
// 如果测试catch路径
inq.mock(radioStateHelper, "updateState").returns(Promise.reject(new Error(“failedNow”));