likes
comments
collection
share

用Jest测试JavaScript中的拒绝承诺

作者站长头像
站长
· 阅读数 30

代码

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

另请参见

转载自:https://juejin.cn/post/7125708042603085831
评论
请登录