Jest文档说:
未兑现的promise
如果Promise根本没有解决,则可能会引发此错误:
(等等)
在我的情况下,这不会发生。我有这个测试:
test('detect infinite loop', () => {
expect.assertions(1);
const vastPromise = VastUtils.parseFromUrl(infiniteLoopUrl);
const expectedError =
new VastError(VastErrorCodes.WRAPPER_LIMIT_REACHED);
return expect(vastPromise).rejects.toEqual(expectedError);
});
VastUtils
简单地获取一个位于infiniteLoopUrl
的XML,解析它,如果这个xml指向另一个xml,VastUtils
按照链接,解析新的xml,合并它们并重复这个过程。现在,infiniteLoopUrl
指向一个引用自己的XML,所以它是一个无限循环。“正确”,代码无限地遵循xml链接,并且永远不会解决或拒绝promise。
我期望上述测试在一定超时后失败,但它没有。
有人能帮我吗?谢谢
编辑:我试图用一个较小的例子重现一个无限的Promise循环,这就是我注意到的:
此测试在5s后正确失败:
test('Promise2', () => {
const genPromise = (): Promise<void> => {
return new Promise((res) => {
setTimeout(() => {
res();
}, 200);
})
.then(() => {
return genPromise();
});
};
const vastPromise = genPromise();
const expectedError =
new VastError(VastErrorCodes.WRAPPER_LIMIT_REACHED);
return expect(vastPromise).rejects.toEqual(expectedError);
});
此测试在5s后不失败(笑话保持在无限循环中)
test('Promise', () => {
const genPromise = (prom: Promise<void>): Promise<void> => {
return prom
.then(() => {
return genPromise(Promise.resolve());
});
};
const vastPromise = genPromise(Promise.resolve());
const expectedError =
new VastError(VastErrorCodes.WRAPPER_LIMIT_REACHED);
return expect(vastPromise).rejects.toEqual(expectedError);
});
显然这些是相似的,但我不明白导致笑话无限循环的区别…
好的,我明白问题了。
原因是js的单线程特性。在编辑部分的两个例子中,第一个例子有超时,所以jest有一段时间可以控制并检查超时。在第二个例子中没有,所以jest从不检查超时。
在我的真实案例中,问题是假服务器:它被创建为:
server = sinon.fakeServer.create({
respondImmediately: true
});
立即使sinon同步响应,因此jest永远无法控制。将其创建为:
server = sinon.fakeServer.create({
autoRespond: true
});
sinon在10ms后响应,jest可以检查时间流逝