【发布时间】:2023-04-30 09:49:01
【问题描述】:
请记住,我对 Jest 还很陌生,而且我对 Node 的
Promise
的内部结构并不十分熟悉。我知道
async
函数实际上是返回
Promise
的函数,我在这种想法上取得了很好的成功。
我有一个正在尝试测试的功能。它具有在执行任何其他工作之前导入的依赖项。根据传递给
foo
的输入,该依赖项可能会返回不同的内容,这些内容可能会或可能不会影响
foo
的结果。它是这样的:
// foo.js
const someOtherWork = require("../bar/baz");
module.exports = async function foo() {
const array = await someOtherWork();
... do other things ...
return someStuff;
}
我导入了一个函数来帮助完成
foo
正在尝试做的工作。
在我的测试中,我像这样监视
someOtherWork
函数:
// foo.test.js
const someOtherWork = jest.requireActual("../bar/baz");
const mockSomeOtherWork = jest.fn().mockImplementation(someOtherWork);
jest.mock("../bar/baz", () => mockSomeOtherWork);
const foo = require("./foo.js");
// ...tests...
有了这个,我可以断言
mockSomeOtherWork
是用特定参数调用的,甚至它返回了正确的输出。当我的模拟依赖项(在这种情况下为
someOtherWork
)返回
Promise
时,我被绊倒了。
当我尝试断言
Promise
解析为特定值
而不在我的测试代码中调用模拟函数
时,它
总是
通过了测试: p>
expect(mockSomeOtherWork).toHaveReturnedWith(Promise.resolve([my, array, of, expected, values])); // succeeds correctly
expect(mockSomeOtherWork).toHaveReturnedWith(Promise.reject("lol nope"); // succeeds ERRONEOUSLY
当我断言它返回
Array
或其他任何东西时,我已经成功地失败了测试,如下所示:
expect(mockSomeOtherWork).toHaveReturnedWith(Array); // fails correctly
expect(mockSomeOtherWork).toHaveReturnedWith([my, array, of, expected, values]); // fails correctly
但是任何形式的
Promise
通过
测试,这意味着我不能从我的断言中假设任何内容!
我开始发现,对于 Jest,
Promise
是一个非常不透明的对象,我必须
await
它或附加回调(通过
then
或
catch
)来弄清楚里面是什么. Promise 是否不记得它们已经解析的值供我稍后检查,而无需重新调用返回它的函数?我不想依赖断言
someOtherWork
的其他依赖项或
foo
的返回值,因为这些选项假设了很多关于
foo
的内容,这些内容可能随时发生变化。我在
someOtherWork
上已经有了一个有效的间谍模拟工具。我应该改为从
mockSomeOtherWork.mock.results[0].value
和
await
中获取返回的
Promise
吗?是否有一种“正确”的方式来断言被测单元的依赖关系的
async
结果?