Функция вызова Jest React Typescript

У меня есть этот компонент, который я пытаюсь протестировать, но что бы я ни пытался, я получаю ошибки:

import {useEffect, useState} from 'react';
import {useUser} from '.';

/**
 * Check If the company is locked
 */
export const useIsCompanyLocked = (): boolean => {
  const userInfo = useUser();
  const [status, setStatus] = useState(false);

  useEffect(() => {
    if (!userInfo) {
      return;
    }

    (async (): Promise<void> => {
      setStatus(false);
      // Do some stuff
      setStatus('do some condition which returns a boolean result');
    })();
  }, [userInfo, status]);

  return status;
};

И вот мой шуточный тест, который не удался:

/**
 * @jest-environment jsdom
 */
import {useIsCompanyLocked} from '../useIsCompanyLocked';
import {mockUseUser} from '@myTest/test-utilities';
import React from 'react';

// eslint-disable-next-line @typescript-eslint/no-var-requires
const appUtils = require('@myTest/app-utilities');

describe('useUserHasSecurityPermissionForCompany', () => {
  const setStatus = jest.fn();
  let useStateSpy: any;

  beforeEach(() => {
    useStateSpy = jest.spyOn(React, 'useState');
    useStateSpy.mockImplementation((initialState: any) => [initialState, setStatus]);
  });

  it('should return "false" if user is Admin', () => {
    let mockUser = mockUseUser();
    mockUser = {
      ...mockUser,
      isAdmin: true
      ]
    };
    jest.spyOn(appUtils, 'useUser').mockReturnValue(mockUser);
    const obj = useIsCompanyLocked();
    expect(obj).toEqual(false);
  });
});

Я пробовал много разных итераций этого теста, но всегда получал какую-то ошибку. Как правильно протестировать эту функцию «useIsCompanyLocked»?

Вот ошибка, которую я получаю:

Summary of all failing tests
FAIL src/hooks/__tests__/useIsCompanyLocked.test.tsx (10.631s)
  ● useIsCompanyLocked › should return "false" if user is Admin

    expect(received).toEqual(expected) // deep equality

    Expected: false
    Received: [false, [Function mockConstructor]]

      39 |     jest.spyOn(appUtils, 'useUser').mockReturnValue(mockUser);
      40 |     const obj = useIsCompanyLocked();
    > 41 |     expect(obj).toEqual(false);
         |                 ^
      42 |   });
      43 |

      at Object.<anonymous> (src/hooks/__tests__/useIsCompanyLocked.test.tsx:41:17)

Какие у вас проблемы или ошибки? Я предполагаю, что это что-то вроде нарушения правил использования перехватчиков, поскольку вы пытаетесь вызвать перехватчик React напрямую, вне любого компонента React или специального перехватчика React. Можете ли вы отредактировать , чтобы уточнить конкретную/конкретную проблему/проблему, которая у вас возникла, включить полное сообщение(я) об ошибке и все сопутствующие трассировки стека ошибок, а если есть более подходящий код, полный минимальный воспроизводимый пример ?

Drew Reese 20.03.2024 01:33

Как сказано выше, вы не можете проверить свой крючок, вызвав его напрямую. Я думаю, вам нужно использовать дополнительные инструменты тестирования, такие как renderhook из response-hooks-testing-library.

het 20.03.2024 01:42

@DrewReese да, это нарушает правила хуков. Как правильно протестировать крючок?

joshKDev 20.03.2024 14:30

@het это большой проект компании, я стараюсь не добавлять новую библиотеку или инструмент тестирования. Я не могу найти в нашей существующей библиотеке пример того, как кто-то тестирует перехват, но мне необходимо добавить тестирование, поскольку я добавляю этот новый перехват.

joshKDev 20.03.2024 14:31

@DrewReese Я отредактировал свой вопрос, включив в него последнее сообщение об ошибке.

joshKDev 20.03.2024 14:35
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
5
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема

Проблема здесь в том, что ваш код модульного теста вызывает перехватчик React напрямую, а не внутри компонента React или специального перехватчика React.

Решение

Распространенный метод модульного тестирования перехватчиков React — использование утилиты React-Hooks-Testing-Library renderHook. Скорее всего, вы уже используете React-Testing-Library (если вы этого не делаете, вам действительно следует рассмотреть возможность ее использования, поскольку это стандартная библиотека тестирования для пользовательского интерфейса React), в которую включена библиотека тестирования перехватов React.

Подробности смотрите в renderHook.

Основной пример использования:

/**
 * @jest-environment jsdom
 */
import React from 'react';
import { renderHook } from '@testing-library/react';
import { mockUseUser } from '@myTest/test-utilities';
import { useIsCompanyLocked } from '../useIsCompanyLocked';

// eslint-disable-next-line @typescript-eslint/no-var-requires
const appUtils = require('@myTest/app-utilities');

describe('useUserHasSecurityPermissionForCompany', () => {
  it('should return "false" if user is Admin', async () => {
    // Prime useUser hook to return user with "isAdmin: true"
    const mockUser = mockUseUser();
    mockUser.isAdmin = true;
    jest.spyOn(appUtils, 'useUser').mockReturnValue(mockUser);

    const { result } renderHook(() => useIsCompanyLocked());

    expect(result.current).toEqual(false);
  });
});

Дополнительным способом тестирования вашего хука useIsCompanyLocked является асинхронная логика в хуке useEffect, которая обновляет состояние status, которое вы действительно хотите подтвердить. Для этого вам нужно подделать эту логику и использовать утилиту act, чтобы «разрешить» ее и запустить «повторный рендеринг», чтобы тест мог получить доступ к состоянию status после того, как асинхронная логика эффекта обновила состояние с результатом издеваемый объект пользователя.

/**
 * @jest-environment jsdom
 */
import React from 'react';
import { act, renderHook } from '@testing-library/react';
import { mockUseUser } from '@myTest/test-utilities';
import { useIsCompanyLocked } from '../useIsCompanyLocked';

// eslint-disable-next-line @typescript-eslint/no-var-requires
const appUtils = require('@myTest/app-utilities');

describe('useUserHasSecurityPermissionForCompany', () => {
  it('should return "false" if user is Admin', async () => {
    // Setup/mock the asynchronous logic
    const resolvedPromise = Promise.resolve(/* whatever the logic needs in the hook */);
    // any additional mocks, e.g. `fetch` or `axios`, etc

    // Prime useUser hook to return user with "isAdmin: true"
    const mockUser = mockUseUser();
    mockUser.isAdmin = true;
    jest.spyOn(appUtils, 'useUser').mockReturnValue(mockUser);

    const { result } renderHook(() => useIsCompanyLocked());

    // wait for the asynchronous logic to complete
    await act(() => resolvedPromise);

    expect(result.current).toEqual(false);
  });
});

Другие вопросы по теме