用 Jest 模拟 React 自定义钩子
Posted
技术标签:
【中文标题】用 Jest 模拟 React 自定义钩子【英文标题】:Mocking React custom hook with Jest 【发布时间】:2021-03-23 23:38:28 【问题描述】:在对 React 组件进行单元测试时,我需要模拟我的自定义钩子。我已经阅读了一些关于这个简单任务的教程和 *** 答案,但没有正确实现它。
我最简单的单一测试设置如下:
// TestComponent.js
import React from "react";
import useTest from "./useTest";
const TestComponent = () =>
const state = useTest("initial_value");
return <div>state</div>;
;
export default TestComponent;
// useTest.jsx - simple custom hook
import React, useState from "react";
const useTest = (initialState) =>
const [state] = useState(initialState);
return state ;
;
export default useTest;
// TestComponent.test.jsx - my test case
import React from "react";
import render from "@testing-library/react";
import TestComponent from "./TestComponent";
jest.mock("./useTest", () => (
useTest: () => "mocked_value",
));
test("rendertest", () =>
const component = render(<TestComponent />);
expect(component.container).toHaveTextContent("mocked_value");
);
所以我试图模拟 useTest
自定义钩子以返回“mocked_value”,而不是来自真正的自定义钩子的“initial_value”。但上面的代码只是给了我这个错误:
TypeError: (0 , _useTest.default) is not a function
3 |
4 | const TestComponent = () =>
> 5 | const state = useTest("initial_value");
| ^
6 |
7 | return <div>state</div>;
8 | ;
我也试过了:
import useTest from './useTest';
// ...
jest.spyOn(useTest, "useTest").mockImplementation(() => "mocked_value");
import useTest from './useTest';
// ...
jest.spyOn(useTest, "useTest").mockReturnValue("mocked_value");
但两者都给我错误Cannot spy the useTest property because it is not a function; undefined given instead
。
如何实施这个测试?
【问题讨论】:
【参考方案1】:我在回答自己。这样就可以了:
jest.mock("./useTest", () => (
useTest: () => ( state: 'mocked_value' ),
));
如果我想在自定义挂钩中使用默认导出:
jest.mock("./useTest", () => (
__esModule: true,
default: () => ( state: 'mocked_value' ),
));
另外,如果我还想在我的钩子中使用setState
方法并导出它,我可以这样模拟它:
const mockedSetState = jest.fn();
jest.mock("./useTest", () => (
useTest: () => ( state, setState: mockedSetState ),
));
现在可以检查setState
是否被调用过一次:
expect(mockedSetState).toHaveBeenCalledTimes(1);
【讨论】:
非常感谢。 默认导出解决方案非常适合我!谢谢!【参考方案2】:由于您在 useTest 模块中使用export default useTest
,它希望从您的模拟中的默认属性中获取该函数引用。
试试这个:
jest.mock("./useTest", () => (
default: () => "mocked_value",
));
如果你想避免混淆,你可以在 useTest 模块中尝试export const useTest = ...
,然后在你的组件中尝试import useTest from './useTest'
。如果使用这种方法,则无需更改测试。
【讨论】:
感谢您的提示,但这也不起作用。我尝试在jest.mock
函数中将“useTest”更改为“默认”,还尝试使用export default useTest...
导出useTest
挂钩,但没有一个有效。总是同样的错误TypeError: (0 , _useTest.default) is not a function
。
我通过稍微修改它使其工作(见我自己的答案),但感谢这个导出技巧,这很有价值!以上是关于用 Jest 模拟 React 自定义钩子的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 JEST、Enzyme 在 React 中测试自定义钩子?
如何使用 react-hooks-testing-library 测试自定义 async/await 钩子