在单位测试中,如何处理PromiseRepenthandLeDledSwarning?

发布于 2025-02-02 21:00:13 字数 1450 浏览 4 评论 0原文

考虑一下这个可怕的功能,它仍然是我真正问题的模拟:

async function rejectingFunction() {
    await new Promise((resolve) => setTimeout(resolve, 10000000));
    throw new Error("Boom");
}

现在,我需要为此编写一些单元测试。我不想等待我投入的随机数,所以我还会使用sinon库伪造计时器进行测试的能力:

describe("test suite", () => {
    it("should reject", async () => {
        const timers = sinon.useFakeTimers();
        let threw = false;

        try {
            const promise = rejectingFunction();
            await timers.runAllAsync();          // this is required for setTimeout to resolve
            await promise;                       // trap the rejection
        } catch (e) {
            threw = true;
            should.equal("Boom", e.message);
        } finally {
            timers.restore();
        }

        should(threw).be.true();
    });
});

足够容易(忽略笨拙的“确实如此”不要投掷“检测,这不是这里的重点...)。但是,让我们进行测试以确保:

test suite
    ✔ should reject
(node:7319) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
(Use `node --trace-warnings ...` to show where the warning was created)


1 passing (9ms)

测试通过了,并没有永远接受,但是我们会收到不必要的警告。我了解为什么会发生这种情况(我既没有接球手,也没有等待拒绝发生的游戏),但是在这种情况下,这种行为是可以预期的。

是否有一些方法可以表明拒绝可以发生,我保证我很快就会做到这一点?我尝试添加一个空的捕获处理程序,但这只是将拒绝变成了一个分辨率,这不是我想要的。我还尝试添加一个踢脚踢的捕获处理程序会引起警告的源。在运行timers.runallasync()之前,我也无法等待承诺,否则它将悬挂,因为时钟被暂停。

Consider this awful function which nevertheless serves as a simulacrum of my real problem:

async function rejectingFunction() {
    await new Promise((resolve) => setTimeout(resolve, 10000000));
    throw new Error("Boom");
}

Now, I need to write some unit tests for it. I don't want to wait however long that random number I put in is, so I'll also use the sinon library's ability to fake timers to do the testing:

describe("test suite", () => {
    it("should reject", async () => {
        const timers = sinon.useFakeTimers();
        let threw = false;

        try {
            const promise = rejectingFunction();
            await timers.runAllAsync();          // this is required for setTimeout to resolve
            await promise;                       // trap the rejection
        } catch (e) {
            threw = true;
            should.equal("Boom", e.message);
        } finally {
            timers.restore();
        }

        should(threw).be.true();
    });
});

Easy enough (ignore the clunky "did not throw" detection, that's not the point here...). But, let's run the test to be sure:

test suite
    ✔ should reject
(node:7319) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
(Use `node --trace-warnings ...` to show where the warning was created)


1 passing (9ms)

The test passed, and didn't take forever, but we get an unwanted warning. I understand why it is happening (I had neither a catch handler, nor an await in play at the time that the rejection happened), but in this case the behaviour is expected.

Is there some way to indicate that it's okay for the rejection to happen, and I promise I will get to it shortly? I've tried adding an empty catch handler, but that just turns the rejection into a resolution, which isn't what I want. I also tried adding a catch handler that throws just kicks moves the source of the warning. I also can't await on the promise before I run timers.runAllAsync(), or else it will hang because the clock is paused.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你げ笑在眉眼 2025-02-09 21:00:13

如何将catch处理程序直接链接到拒绝函数调用?如:

const timers = sinon.useFakeTimers();
let threw = false;

const promise = rejectingFunction().catch((e) => {
  threw = true;
  should.equal("Boom", e.message);
});

await timers.runAllAsync();
await promise;

timers.restore();

should(threw).be.true();

How about chaining a catch handler directly to the rejectingFunction invocation? As in:

const timers = sinon.useFakeTimers();
let threw = false;

const promise = rejectingFunction().catch((e) => {
  threw = true;
  should.equal("Boom", e.message);
});

await timers.runAllAsync();
await promise;

timers.restore();

should(threw).be.true();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文