提问者:小点点

玩笑未解决的promise不会失败


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);
});

显然这些是相似的,但我不明白导致笑话无限循环的区别…


共1个答案

匿名用户

好的,我明白问题了。

原因是js的单线程特性。在编辑部分的两个例子中,第一个例子有超时,所以jest有一段时间可以控制并检查超时。在第二个例子中没有,所以jest从不检查超时。

在我的真实案例中,问题是假服务器:它被创建为:

server = sinon.fakeServer.create({
    respondImmediately: true
});

立即使sinon同步响应,因此jest永远无法控制。将其创建为:

server = sinon.fakeServer.create({
    autoRespond: true
});

sinon在10ms后响应,jest可以检查时间流逝