代码

让我们考虑一个简略的函数,它回来一个Promise ,依据第一个参数
的值,能够解决或回绝:

export default function promiseMe(result, timeout = 1000) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (result instanceof Error || result.startsWith("Error")) {
                reject(result)
            } else {
                resolve(result)
            }
        }, timeout)
    })
}

当用Jest测验异步代码时,唯一要记住的是要从测验中回来Promise ,以便Jest能够
,等待它的解析或回绝。最洁净的方法是用.resolves 匹配器来做:

const successMessage = "Done.";
// with async/await
it("resolves (1)", async () => {
    await expect(promiseMe(successMessage)).resolves.toEqual(successMessage);
});
// without async/await
it("resolves (2)", () => {
    return expect(promiseMe(successMessage)).resolves.toEqual(successMessage);
});

假如Promise 回绝,而测验又没有预料到,Jest会陈述一个过错:

Error: expect(received).resolves.toEqual()
Received promise rejected instead of resolved
Rejected to value: [...]

可是,假如想测验Promise 回绝,并验证回绝的原因呢?

Try-catch与async/await(坏)

看起来运用try-catchasync/await 是实现这一方针的最简略方法,由于回绝值被抛出了:

it("rejects (bad)", async () => {
    try {
        await promiseMe("Error");
    } catch (e) {
        expect(e).toEqual("Error");
    }
});

可是,等等。当promiseMe 函数回来的Promise 不会被回绝,而是解决了,会发生什么?好吧,测验仍然通过,由于从来没有到达过catch块:

拜见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#promise_rejection

Try-catch与async/await(更好)

为了克服这个问题,我们能够预期实际的断语将被执行,假如它没有发生,则测验失败。
这能够用expect.assertions 很容易做到,它验证了在测验期间有一定数量的断语被调用

it("rejects (better)", async () => {
    expect.assertions(1);
    try {
        await promiseMe("Error");
    } catch (e) {
        expect(e).toEqual("Error");
    }
});

现在,当没有回绝时,测验失败:

Error: expect.assertions(1)
Expected one assertion to be called but received zero assertion calls.

.rejects (最佳)

为了使代码更有表现力,能够运用.rejects 匹配器:

it("rejects (best)", async () => {
    await expect(promiseMe("Error")).rejects.toEqual("Error");
});

当没有回绝时,Jest陈述一个过错:

Error: expect(received).rejects.toEqual()
Received promise resolved instead of rejected  
Resolved to value: [...]  

假如回绝的值是一个Error 目标,能够运用toThrow 匹配器:

it("rejects (best)", async () => {
    await expect(promiseMe(new Error(errorMessage))).rejects.toThrow(errorMessage);
    await expect(promiseMe(new Error(errorMessage))).rejects.toThrow(Error); // type check
    await expect(promiseMe(new Error(errorMessage))).rejects.toThrow(new Error(errorMessage));
});

另请拜见

  • 用Jest测验JavaScript中的异常
  • Jest Vanilla JS Starter
  • 在JUnit中处理异常的不同方法,该选择哪一种?