Тестирование useContext хука

Хук useContext является важной частью функциональных компонентов в React, предоставляя возможность получения значения контекста в компоненте. Для тестирования компонентов, использующих этот хук, важно правильно настроить контекст в тестах и обеспечить корректную работу проверок. В этой статье рассматривается, как эффективно тестировать компоненты, использующие useContext, с использованием библиотеки Enzyme.

Настройка контекста в тестах

Для тестирования хука useContext необходимо создать контекст и обернуть компонент в его провайдер. Это позволяет передать нужные значения контекста в тестируемый компонент, чтобы проверить его поведение при различных состояниях контекста.

  1. Создание контекста

Прежде всего, нужно создать контекст с помощью функции React.createContext:

const MyContext = React.createContext();
  1. Использование контекста в компоненте

Компонент, использующий хук useContext, может выглядеть следующим образом:

const MyComponent = () => {
  const contextValue = useContext(MyContext);
  return <div>{contextValue}</div>;
};
  1. Обертывание компонента в провайдер контекста

Чтобы компонент получал значения контекста, его нужно обернуть в провайдер контекста в тестах:

const wrapper = shallow(
  <MyContext.Provider value="Test Value">
    <MyComponent />
  </MyContext.Provider>
);

В этом примере компонент MyComponent будет получать значение “Test Value” через хук useContext и выводить его на экран.

Проверка корректности работы контекста

После того как контекст настроен в тестах, можно проверить, что компонент правильно отобразил переданное значение контекста. Для этого можно использовать методы Enzyme, такие как shallow, mount и dive.

  1. Использование shallow для тестирования

Метод shallow позволяет рендерить компонент без его дочерних элементов. В случае с контекстом это полезно, если нужно проверить, как компонент использует контекст, не взаимодействуя с более глубокими уровнями дерева компонентов.

Пример теста с использованием shallow:

it('отображает значение контекста', () => {
  const wrapper = shallow(
    <MyContext.Provider value="Test Value">
      <MyComponent />
    </MyContext.Provider>
  );
  expect(wrapper.text()).toEqual('Test Value');
});
  1. Использование mount для тестирования с дочерними компонентами

Метод mount позволяет рендерить полный компонент с дочерними элементами. Это полезно, когда нужно проверить взаимодействие между несколькими компонентами, использующими контекст.

Пример теста с использованием mount:

it('проверяет, что дочерний компонент получает контекст', () => {
  const ChildComponent = () => {
    const contextValue = useContext(MyContext);
    return <div>{contextValue}</div>;
  };

  const wrapper = mount(
    <MyContext.Provider value="Test Value">
      <ChildComponent />
    </MyContext.Provider>
  );
  expect(wrapper.find(ChildComponent).text()).toEqual('Test Value');
});
  1. Проверка изменения контекста

Иногда важно убедиться, что компонент правильно обновляется при изменении значения контекста. Для этого можно использовать компонент-обертку, который изменяет состояние контекста, и проверять, как компонент реагирует на изменение.

Пример теста с обновлением контекста:

it('обновляет значение при изменении контекста', () => {
  const [value, setValue] = useState('Initial Value');
  const wrapper = mount(
    <MyContext.Provider value={value}>
      <MyComponent />
    </MyContext.Provider>
  );

  expect(wrapper.text()).toEqual('Initial Value');
  
  setValue('Updated Value');
  wrapper.update();
  
  expect(wrapper.text()).toEqual('Updated Value');
});

Мокирование контекста

В некоторых случаях полезно использовать мокированные контексты для тестирования компонентов в различных состояниях без необходимости изменения реальных значений контекста. Для этого можно использовать функцию jest.fn() для создания мока контекста.

Пример мокирования контекста:

const mockContextValue = jest.fn(() => 'Mocked Value');

it('использует мокированный контекст', () => {
  const wrapper = shallow(
    <MyContext.Provider value={mockContextValue()}>
      <MyComponent />
    </MyContext.Provider>
  );
  expect(wrapper.text()).toEqual('Mocked Value');
});

Тестирование компонента с контекстом и состоянием

Когда компонент использует как контекст, так и внутреннее состояние, важно протестировать взаимодействие между этими двумя источниками данных. В таких случаях можно комбинировать тестирование хука useContext с обычными проверками состояния компонента.

Пример компонента с контекстом и состоянием:

const MyComponentWithState = () => {
  const contextValue = useContext(MyContext);
  const [stateValue, setStateValue] = useState('Initial State');
  
  return (
    <div>
      <p>{contextValue}</p>
      <p>{stateValue}</p>
      <button onCl ick={() => setStateValue('Updated State')}>Update State</button>
    </div>
  );
};

Пример теста:

it('отображает состояние и контекст', () => {
  const wrapper = shallow(
    <MyContext.Provider value="Test Context Value">
      <MyComponentWithState />
    </MyContext.Provider>
  );
  
  expect(wrapper.find('p').at(0).text()).toEqual('Test Context Value');
  expect(wrapper.find('p').at(1).text()).toEqual('Initial State');
  
  wrapper.find('button').simulate('click');
  expect(wrapper.find('p').at(1).text()).toEqual('Updated State');
});

Обработка ошибок и отлов исключений

В случае, если компонент использует useContext для получения данных, важно убедиться, что обработка ошибок происходит корректно, если контекст не был предоставлен. Для этого можно добавить проверки на наличие значений в контексте или использовать дефолтные значения.

Пример с дефолтным значением:

const MyContext = React.createContext('Default Value');

it('использует дефолтное значение контекста', () => {
  const wrapper = shallow(<MyComponent />);
  expect(wrapper.text()).toEqual('Default Value');
});

Если контекст не был передан, компонент будет использовать дефолтное значение.

Заключение

Тестирование компонентов, использующих хук useContext, требует корректной настройки контекста в тестах, а также проверки правильного использования этого контекста компонентами. Использование Enzyme с методами shallow и mount позволяет эффективно тестировать взаимодействие компонентов с контекстом, а также проверять их корректность при изменении контекста или состояния.