tra*_*jan 6 javascript async-await reactjs jestjs
jest.fn()我对从使用创建的干净 CRA 项目运行时的以下行为感到困惑npx create-react-app jest-fn-behaviour。
例子:
describe("jest.fn behaviour", () => {
const getFunc = async () => {
return new Promise((res) => {
setTimeout(() => {
res("some-response");
}, 500)
});;
}
const getFuncOuterMock = jest.fn(getFunc);
test("works fine", async () => {
const getFuncInnerMock = jest.fn(getFunc);
const result = await getFuncInnerMock();
expect(result).toBe("some-response"); // passes
})
test("does not work", async () => {
const result = await getFuncOuterMock();
expect(result).toBe("some-response"); // fails - Received: undefined
})
});
Run Code Online (Sandbox Code Playgroud)
上述测试将在干净的 JavaScript 项目中按预期工作,但在 CRA 项目中则不然。
有人可以解释为什么第二次测试失败吗?在我看来,当在jest.fn()非异步函数(例如describe上面)中调用时,模拟异步函数将无法按预期工作。仅当在异步函数(test上面)中调用时它才起作用。但为什么 CRA 会以这种方式改变行为呢?
原因是,正如我在另一个答案中提到的,CRA 的默认 Jest 设置包括以下行:
\n resetMocks: true,\nRun Code Online (Sandbox Code Playgroud)\n根据Jest 文档,这意味着(强调我的):
\n\n\n每次测试前自动重置模拟状态。相当于每次测试之前\n调用
\njest.resetAllMocks()。这将导致任何模拟删除其虚假实现,但不会恢复其初始实现。
正如我在评论中指出的,您的模拟是在测试发现时创建的,当 Jest 查找所有规范并调用describe(但不是it/ test)回调时,而不是在执行时创建,当它调用规范回调时。因此,它的模拟实现是毫无意义的,因为它在任何测试运行之前就被清除了。
相反,您有三个选择:
\n正如您所看到的,在测试本身内创建模拟是可行的。在测试中重新配置现有的模拟也可以,例如getFuncOuterMock.mockImplementation(getFunc)(或只是getFuncOuterMock.mockResolvedValue("some-response"))。
您可以将模拟创建和/或配置移动到beforeEach回调中;这些在所有模拟重置后执行:
describe("jest.fn behaviour", () => {\n let getFuncOuterMock;\n // or `const getFuncOuterMock = jest.fn();`\n\n beforeEach(() => {\n getFuncOuterMock = jest.fn(getFunc);\n // or `getFuncOuterMock.mockImplementation(getFunc);`\n });\n\n ...\n});\nRun Code Online (Sandbox Code Playgroud)\nresetMocks是 CRA 支持的用于覆盖 Jest 配置的键之一,因此您可以添加:
"jest": {\n "resetMocks": false\n },\nRun Code Online (Sandbox Code Playgroud)\n进入你的package.json.
但是,请注意,这可能会导致误报测试,由于在不同的expect(someMock).toHaveBeenCalledWith(some, args)测试中与模拟进行交互,您和它都会通过。如果您要禁用自动重置,您还应该更改创建模拟的实现(即选项 2 中的示例),以避免测试之间的状态泄漏。beforeEachlet getFuncOuterMock;
请注意,这与同步与异步无关,也与模拟生命周期无关;您会在 CRA 项目(或具有resetMocks: trueJest 配置的普通 JS 项目)中看到与以下示例相同的行为:
describe("the problem", () => {\n const mock = jest.fn(() => "foo");\n\n it("got reset before I was executed", () => {\n expect(mock()).toEqual("foo");\n });\n});\nRun Code Online (Sandbox Code Playgroud)\n \xe2\x97\x8f the problem \xe2\x80\xba got reset before I was executed\n\n expect(received).toEqual(expected) // deep equality\n\n Expected: "foo"\n Received: undefined\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
965 次 |
| 最近记录: |