[英]Promise not rejecting correctly in Jest test
当承诺拒绝使用 Jest 时,我正在尝试测试console.error
输出。 我发现在我的测试运行后,承诺似乎正在解决,导致测试失败。
示例函数:
export default function doSomething({ getData }) {
const success = data => {
//do stuff with the data
}
const handleError = () => {
//handle the error
}
getData.then(response => success(response)).catch(error => {
console.error(error)
handleError()
})
}
示例测试文件:
import doSomething from "doSomething"
it("should log console.error if the promise is rejected", async () => {
const getData = new Promise((resolve, reject) => {
reject("fail");
});
global.console.error = jest.fn();
await doSomething({ getData });
expect(global.console.error).toHaveBeenCalledWith("fail");
})
//fails with global.console.error has not been called
当我探索这个问题时,我注意到如果我添加一个 console.log 并等待它,它就可以工作。
这将通过...
import doSomething from "doSomething"
it("should log console.error if the promise is rejected", async () => {
const getData = new Promise((resolve, reject) => {
reject("fail");
});
global.console.error = jest.fn();
await doSomething({ getData });
await console.log("anything here");
expect(global.console.error).toHaveBeenCalledWith("fail");
})
我如何正确测试? 我应该重构我的getData
函数的调用方式吗? 一旦doSomething
函数被调用,它就需要被调用。
为什么原始测试失败?
理解为什么第一个测试示例不会通过的技巧是深入研究await
运算符实际在做什么。 来自Mozilla 文档:
[rv] = await expression;
expression
- 一个 Promise 或任何要等待的值。rv
- 返回 Promise 的已履行值,如果它不是 Promise,则返回值本身。 在您的第一个测试中, expression
的值是doSomething
函数的返回值。 您不会从此函数返回任何内容,因此返回值将为undefined
。 这不是一个 Promise,所以await
什么都不做,它只会返回undefined
并继续前进。 expect
语句将失败,因为您实际上还没有等待内部承诺: getData.then(...).catch(...)
。
要修复测试,而不添加额外的行,请await console.log("anything here");
, 只需从doSomething
函数return
内部承诺,以便await
运算符将实际操作 Promise。
export default function doSomething({ getData }) {
return getData.then(...).catch(...);
...
}
这是测试这个的正确方法吗?
我不认为doSomething
函数的编写方式有什么大问题。 这种依赖注入通常使函数更容易测试,而不是试图模拟函数的内部工作。
我只承认,因为您正在注入一个 Promise ( getData
),并在函数内解析它,所以您使doSomething
函数异步(这使得测试变得更加复杂)。
如果您解析了 Promise,然后在它解析为的值上调用doSomething
, getData.then(doSomething).catch(handleError)
,您的doSomething
函数将是同步的并且更容易测试。 我还要说,以这种方式编写它会使异步发生的事情变得更加冗长,而原始的doSomething({ getData })
将其隐藏在doSomething
函数体中。
所以没有什么是严格不正确的,但也许需要考虑的一些事情可能会使测试更容易并且代码更冗长。 我希望这有帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.