#reactjs #jestjs #mocking #react-hooks
#reactjs #jestjs #издевательство #реагирующие хуки
Вопрос:
Мне нужно издеваться над моим пользовательским хуком при модульном тестировании компонента React. Я прочитал несколько руководств и ответов 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;
// 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:
Поскольку вы используете export default useTest
модуль in useTest, он ожидает получить ссылку на эту функцию из атрибута по умолчанию в вашем макете.
Попробуйте это:
jest.mock("./useTest", () => ({
default: () => "mocked_value",
}));
Если вы хотите избежать путаницы, вы можете попробовать export const useTest = ...
в модуле useTest, а затем import { useTest } from './useTest'
в вашем компоненте. При использовании этого подхода нет необходимости изменять ваш тест.
Комментарии:
1. Спасибо за совет, но это тоже не работает. Я попытался изменить «useTest» на «default» в
jest.mock
функции, а также попытался экспортироватьuseTest
хук сexport default useTest...
помощью, но ничего не работает. Всегда одна и та же ошибкаTypeError: (0 , _useTest.default) is not a function
.2. Я заставил его работать, слегка изменив его (см. Мой собственный Ответ), но спасибо за этот совет по экспорту, это было ценно!
Ответ №3:
Для тех, кто использует правильный хук, это можно сделать так
import * as useFetchMock from "../../../../hooks/useFetch";
it("should show loading component on button when state is loading", () => {
jest.spyOn(useFetchMock, "default").mockReturnValue({
result: null,
message: null,
status: "pending",
loading: true,
fetch: jest.fn(),
});
render(<Component />);
expect.assertions(1);
expect(screen.getByTestId(testIdComponentB)).toBeInTheDocument();
});
импортируйте свой пользовательский хук напрямую и используйте «по умолчанию» для прямого взаимодействия