I'm trying to mock the methods & hooks in a file and import those mock functions as I need them, in my test files.
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>
);
};
this is the file where i mock the hooks & functions.
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 };
the useMyHook
hook is a bare minimum hook which just returns a value(state).
i'm importing the mocks
variable in my test file and calling mocks.useMyHook()
, but it doesn't work. I still get the original hook's value in return while testing.
I'm testing a Hello.jsx
component which uses useMyHook
hooks and logs its return value in console.
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()
});
});
when i run the test, I still see the original hook's value being logged in console, instead of the mock value(12345).
I found out that using jest.mock
before the describe
instead of jest.spyOn
works.
But I have a lot of tests that change the mocked value during the tests(like inside a specific test()
block) by calling mocks.useMyHook
and the hook would return another value for that specific test cases.
The spyOn
method used to work previously fine, but alot of things changed in the project so now I'm unable to make it work.
I'm on a next js project. Here's some info on the project:
dependencies:
{
...
"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": []
}
EDIT: Typo & Added useMyHook
hook & Hello
component code.