用Jest测试JavaScript中的拒绝承诺

代码

让我们考虑一个简单的函数,它返回一个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));
});
复制代码

另请参见

猜你喜欢

转载自juejin.im/post/7125708042603085831
今日推荐