Javascript 断言forEach循环内的catch块代码
我很难编写测试来断言catch块中发生的事情,而catch块是在Javascript 断言forEach循环内的catch块代码,javascript,foreach,try-catch,sinon,sinon-chai,Javascript,Foreach,Try Catch,Sinon,Sinon Chai,我很难编写测试来断言catch块中发生的事情,而catch块是在forEach循环中执行的 产品代码 function doSomething(givenResourceMap) { givenResourceMap.forEach(async (resourceUrl) => { try { await axios.delete(resourceUrl); } catch (error) { logger.error(`Error on
forEach
循环中执行的
产品代码
function doSomething(givenResourceMap) {
givenResourceMap.forEach(async (resourceUrl) => {
try {
await axios.delete(resourceUrl);
} catch (error) {
logger.error(`Error on deleting resource ${resourceUrl}`);
logger.error(error);
throw error;
}
});
我想断言logger.error
被调用两次,每次都使用正确的参数调用。所以我写了一些这样的测试
describe('Do Something', () => {
it('should log message if fail to delete the resource', function() {
const resource1Url = chance.url();
const givenResourceMap = new Map();
const thrownError = new Error('Failed to delete');
givenResourceMap.set(resource1Url);
sinon.stub(logger, 'error');
sinon.stub(axios, 'delete').withArgs(resource1Url).rejects(thrownError);
await doSomething(givenResourceMap);
expect(logger.error).to.have.callCount(2);
expect(logger.error.getCall(0).args[0]).to.equal(`Error deleting resource ${resource1Url}`);
expect(logger.error.getCall(1).args[0]).to.equal(thrownError);
// Also need to know how to assert about `throw error;` line
});
});
我正在使用摩卡咖啡,西农柴,期待测试。上述测试失败,说明记录器。错误为0次
谢谢。问题在于,您正在对不返回承诺的函数使用wait
。请注意,doSomething
不是async
,并且不返回Promise
对象
forEach
函数是async
,但这意味着它们将立即返回,并带有一个未解决的承诺
,您永远不会等待它们
实际上,doSomething
将在forEach
内部的工作完成之前返回,这可能不是您想要的。为此,可以使用如下常规for循环:
async function doSomething(givenResourceMap) {
for (const resourceUrl of givenResourceMap) {
try {
await axios.delete(resourceUrl);
} catch (error) {
logger.error(`Error on deleting resource ${resourceUrl}`);
logger.error(error);
throw error;
}
}
}
请注意,它将doSomething
的返回类型更改为Promise
对象,而不是像最初那样仅返回undefined
。但它确实允许您在测试中(可能也在生产代码中)根据需要对其执行wait
但是,由于重新抛出循环中捕获的异常,测试将异常退出。测试代码也必须更改以捕获预期错误:
it('should log message if fail to delete the resource', function(done) {
// ... the setup stuff you had before...
await doSomething(givenResourceMap).catch(err => {
expect(logger.error).to.have.callCount(2);
expect(logger.error.getCall(0).args[0]).to.equal(`Error deleting resource ${resource1Url}`);
expect(logger.error.getCall(1).args[0]).to.equal(thrownError);
done();
});
});
测试通过,即使prod代码中没有logger.error语句。我在测试中尝试了async/await,而不是done。您需要在捕获
中使用您的Expect,因为您确实在错误上抛出了一个异常。done
可能不是强制性的,但不会造成伤害。你现在有什么问题?如果考试通过,你会很高兴,对吗?