用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-catch
与async/await
是实现这一目标的最简单方法,因为拒绝值被抛出了:
it("rejects (bad)", async () => {
try {
await promiseMe("Error");
} catch (e) {
expect(e).toEqual("Error");
}
});
但是,等等。当promiseMe
函数返回的Promise
不会被拒绝,而是解决了,会发生什么?好吧,测试仍然通过,因为从来没有到达过catch块:
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