Три важные вещи о Jest в Next.js
Я абсолютный новичок в Jest, и каждый день я узнаю много нового.
В этой статье я напишу пять вещей, которые я недавно узнал о тестировании Jest в Next.js.
Будь то мокинг или настройка тестового окружения, я запишу всё это в качестве заметки для себя.
1. Использование renderHook для тестирования пользовательских хуков React.
Я хотел протестировать свой пользовательский хук React, useAuth
, который возвращает набор данных пользовательской сессии в объекте. Изначально я пытался протестировать useAuth
следующим образом:
const { session, status, userId } = useAuth();
expect(session).toStrictEqual({ user: { id: 'dummyId' } });
expect(status).toBe('authenticated');
expect(userId).toBe('dummyId');
Однако я столкнулся со следующей ошибкой:
Предупреждение: Неверный вызов хука. Хуки можно вызывать только внутри тела функции компонента.
Чтобы устранить эту ошибку, необходимо вызвать useAuth
с помощью renderHook
из @testing-library/react
:
import { renderHook } from '@testing-library/react';
// ...
const { result } = renderHook(() => useAuth());
const { session, status, userId } = result.current;
Использование renderHook
корректно вызывает useAuth
в нужном контексте и возвращает объект результата, позволяя вам получить доступ к сессии, статусу и ID пользователя без каких-либо ошибок!
2. Всегда помните о mockReset или mockRestore.
Чтобы избежать неожиданного поведения, рекомендуется всегда использовать mockReset
или mockRestore
для сброса макетов между тестами.
Например, рассмотрим следующие тестовые случаи:
it('when status is unauthenticated, router.push is called', () => {
mockUseSession.mockReturnValue({
data: null,
status: 'unauthenticated',
});
renderHook(() => useAuth());
expect(pushMock).toHaveBeenCalledWith('/auth/signin');
});
it('when status is loading, it should return loading as status', () => {
mockUseSession.mockReturnValue({
data: null,
status: 'loading',
});
const { result } = renderHook(() => useAuth());
const { status } = result.current;
expect(status).toBe('loading');
});
В этих тестах mockUseSession
возвращает разные значения с помощью mockReturnValue
. Чтобы гарантировать, что каждое значение макета не будет мешать другим, необходимо сбрасывать макет после каждого теста:
afterEach(() => {
// Reset mockUseSession to avoid test interference
mockUseSession.mockReset();
});
Важно отметить, что в данном случае не следует использовать mockRestore
. mockRestore
удаляет имитатор и восстанавливает исходную функцию. Это означает, что если вы используете mockRestore
, вы полностью потеряете имитатор, и вам придется заново применять его для каждого теста. Это не очень удобно, если вы хотите сохранить имитируемую реализацию, но сбрасывать её состояние между тестами.
3. При использовании Next.Font не забудьте создать имитацию файла next/font/google, чтобы избежать проблем при тестировании.
Если вы используете Next.Font
в своем приложении Next.js, вам необходимо изменить файл next/font/google, чтобы избежать следующей ошибки.
FAIL __tests__/hooks/useModal.test.tsx
● Test suite failed to run
TypeError: (0 , google_1.Mulish) is not a function
В корневом репозитории создайте папку _mocks_
и добавьте в нее файл nextFontMock.js
, содержащий следующий код.
import { jest } from '@jest/globals';
module.exports = {
Staatliches: jest.fn(() => ({
className: 'mocked-staatliches-font',
})),
Mulish: jest.fn(() => ({
className: 'mocked-mulish-font',
})),
...add more
};
и добавьте следующую строку в jest.config.js(ts)
:
moduleNameMapper: {
...other settings,
'next/font/google': '<rootDir>/__mocks__/nextFontMock.js',
},
С этой настройкой каждый раз, когда next/font/google импортируется в ваши тесты, Jest будет использовать вместо него реализацию mock.
Примечание: Это также полезно для подражания конкретным модулям, которые являются сложными или ненужными в контексте ваших тестов.
Заключение
Настроить тестовую среду для меня на самом деле сложнее, чем само тестирование.
Я получал так много ошибок, на решение которых уходило много времени, и это так расстраивало.
Но важно помнить, что тестирование необходимо для безопасного и стабильного приложения, поэтому я должен продолжать учиться и совершенствовать свои навыки.
Спасибо, что читаете!!!