Javascript 在玩笑测试中未正确拒绝的承诺
我正在尝试测试Javascript 在玩笑测试中未正确拒绝的承诺,javascript,promise,jestjs,Javascript,Promise,Jestjs,我正在尝试测试控制台。当承诺使用Jest拒绝时,会出现错误输出。我发现在我的测试运行后,承诺似乎正在解决,导致测试失败 示例函数: export default function doSomething({ getData }) { const success = data => { //do stuff with the data } const handleError = () => { //handle the error } getDa
控制台。当承诺使用Jest拒绝时,会出现错误输出。我发现在我的测试运行后,承诺似乎正在解决,导致测试失败
示例函数:
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
操作符实际在做什么。从:
表达式
-承诺或任何需要等待的值
rv
-返回承诺的已实现值,如果不是承诺,则返回值本身
在第一次测试中,表达式
的值是doSomething
函数的返回值。您没有从该函数返回任何内容,因此返回值将是未定义的
。这不是一个承诺,因此无需等待
执行,它只会返回未定义
并继续。然后,expect
语句将失败,因为您实际上没有等待内部承诺:getData.then(…).catch(…)
要修复测试,无需添加额外的行,wait console.log(“此处的任何内容”)
,只需返回doSomething
函数的内部承诺,这样wait
操作符将实际操作该承诺
export default function doSomething({ getData }) {
return getData.then(...).catch(...);
...
}
这是正确的测试方法吗?
我认为doSomething
函数的编写方式没有什么大问题。这种依赖注入通常使函数比模拟函数的内部工作更容易测试
我只想认识到,因为您正在注入一个承诺(getData
),并在函数中解析它,所以您使doSomething
函数异步(这使得测试更加复杂)
如果您解析了承诺,然后对其解析为的值调用doSomething
,getData.then(doSomething.catch(handleError)
,您的doSomething
函数将是同步的,并且更容易测试。我还想说,以这种方式编写它会使异步发生的事情变得更加冗长,而原来的doSomething({getData})
,将其隐藏在doSomething
函数体中
因此,没有什么是绝对错误的,但可能需要考虑一些事情,这可能会使测试更容易,代码更冗长。我希望这有帮助 谢谢你的解释。缺少return语句是一个简单但非常重要的步骤。你的解决方案很有效。
export default function doSomething({ getData }) {
return getData.then(...).catch(...);
...
}