Reactjs 嘲弄与嘲弄

Reactjs 嘲弄与嘲弄,reactjs,jestjs,mocking,react-hooks,Reactjs,Jestjs,Mocking,React Hooks,在单元测试组件时,我需要模拟我的自定义钩子。对于这个简单的任务,我几乎没有阅读过教程和stackoverflow的答案,但是没有幸正确地实现它 我最简单的单次测试设置如下: // TestComponent.js import React from "react"; import useTest from "./useTest"; const TestComponent = () => { const { state } = useTest(

在单元测试组件时,我需要模拟我的自定义钩子。对于这个简单的任务,我几乎没有阅读过教程和stackoverflow的答案,但是没有幸正确地实现它

我最简单的单次测试设置如下:

// TestComponent.js

import React from "react";
import useTest from "./useTest";

const TestComponent = () => {
  const { state } = useTest("initial_value");

  return <div>{state}</div>;
};

export default TestComponent;
我也尝试过:

import useTest from './useTest';
// ...
jest.spyOn(useTest, "useTest").mockImplementation(() => "mocked_value");
但是两者都给了我错误
无法发现useTest属性,因为它不是一个函数;而不是给定未定义的


如何实现此测试?

由于您在useTest模块中使用了
导出默认useTest
,它希望从模拟中的默认属性获取该函数引用

试试这个:

jest.mock("./useTest", () => ({
  default: () => "mocked_value",
}));

如果希望避免混淆,可以尝试在useTest模块中导出const useTest=…,然后在组件中从“./useTest”导入{useTest}。如果使用此方法,则无需更改测试。

我只回答自己的问题。通过这种方式工作:

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);

谢谢你的提示,但这也不行。我试图在
jest.mock
函数中将“useTest”更改为“default”,并尝试使用
export default useTest…
导出
useTest
钩子,但没有一个能正常工作。始终相同的错误
TypeError:(0,_useTest.default)不是一个函数
。我通过稍微修改它(请参见我自己的答案)使其正常工作,但感谢此导出提示,这很有价值!非常感谢你。
jest.mock("./useTest", () => ({
  useTest: () => ({ state: 'mocked_value' }),
}));
jest.mock("./useTest", () => ({
  __esModule: true,
  default: () => ({ state: 'mocked_value' }),
}));
const mockedSetState = jest.fn();

jest.mock("./useTest", () => ({
  useTest: () => ({ state, setState: mockedSetState }),
}));
expect(mockedSetState).toHaveBeenCalledTimes(1);