jest:无法使用`jest.spyOn`模拟方法/钩子

nszi6y05  于 2023-05-27  发布在  Jest
关注(0)|答案(1)|浏览(194)

我尝试在一个文件中模拟方法和钩子,并在需要时将这些模拟函数导入到我的测试文件中。
useMyHook.jsx

const useMyHook = () => {
  const [val, setVal] = useState(200)

  return { val }
}

export { useMyHook }

Hello.jsx

import { useTestHook } from "@/hooks/useTestHook";

export const Hello = () => {
  const { val } = useTestHook();
  console.log({ val });

  return (
    <div>
      <h2>Hello</h2>
    </div>
  );
};

这是我模仿钩子和函数的文件。mock-hooks.js

import { useMyHook } from "@/hooks/useMyHook";
// import * as Hook from "@/hooks/useMyHook";

const mocks = {
  useMyHook: (val = 9999) => {
    jest
      .spyOn({ useMyHook }, "useMyHook")
      .mockImplementation(() => ({ val }));

    /** this method of mocking used to work before, but now it gives 
        `TypeError: Cannot redefine property: useMyHook` */
    // jest.spyOn(Hook, "useMyHook")
    //   .mockImplementation(() => ({ val }));

  },
};

export { mocks };

useMyHook钩子是仅返回值(状态)的裸最小钩子。
我在我的测试文件中导入mocks变量并调用mocks.useMyHook(),但它不起作用。在测试时,我仍然得到原始钩子的值作为返回。
我正在测试一个Hello.jsx组件,它使用useMyHook钩子并在控制台中记录其返回值。
Hello.test.jsx

import { mocks } from "@/utils/test/mock-hooks";

import { Hello } from "./Hello";
import { render } from "@testing-library/react";

describe("Hello test", () => {
  beforeEach(() => {
    mocks.useMyHook(12345);
    render(<Hello />, {
      wrapper: ({ children }) => <>{children}</>,
    });
  });

  test("should render the main container", () => {
    screen.debug()
  });
});

当我运行测试时,我仍然看到原始钩子的值被记录在控制台中,而不是模拟值(12345)。
我发现在describe之前使用jest.mock而不是jest.spyOn可以工作。但是我有很多测试在测试期间(比如在特定的test()块内)通过调用mocks.useMyHook来改变模拟值,钩子将为特定的测试用例返回另一个值。spyOn方法以前工作得很好,但是项目中有很多事情发生了变化,所以现在我无法让它工作。
我正在做Next.js项目。以下是该项目的一些信息:
依赖性:

{
  ...
 "dependencies": {
    "next": "12.3.0",
    "react": "17.0.2",
    "react-dom": "17.0.2"
  },
  "devDependencies": {
    "@babel/core": "7.17.8",
    "@testing-library/jest-dom": "5.16.4",
    "@testing-library/react": "12.1.2",
    "@testing-library/react-hooks": "7.0.2",
    "babel-jest": "27.4.6",
    "jest": "28.1.0",
    "jest-environment-jsdom": "28.1.0"
  }
}

jest.config.js

const nextJest = require("next/jest");

const createJestConfig = nextJest({});

const customJestConfig = {
  collectCoverageFrom: ["**/*.{js,jsx,ts,tsx}"],
  verbose: true,
  modulePaths: ["<rootDir>/"],
  modulePathIgnorePatterns: ["<rootDir>/.next"],
  testPathIgnorePatterns: ["<rootDir>/node_modules/", "<rootDir>/.next/"],
  transform: {
    "^.+\\.(js|jsx|ts|tsx)$": ["babel-jest", { presets: ["next/babel"] }],
  },
  transformIgnorePatterns: [
    "/node_modules/",
    "^.+\\.module\\.(css|sass|scss)$",
  ],
  testEnvironment: "jsdom",
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/$1",
  },
};

module.exports = createJestConfig(customJestConfig);

.babelrc

{
  "presets": ["next/babel"],
  "plugins": []
}

编辑:错字&添加了useMyHook钩子和Hello组件代码。

rkue9o1l

rkue9o1l1#

仅仅更新jest.config.js的变换属性就解决了这个问题。

transform: {
    '^.+\\.(js|jsx|ts|tsx|mjs)$': ['babel-jest', { presets: ['next/babel'] }]
  },

我还需要把mjs加到变换模式中。
希望这对某人有帮助。

相关问题