Как протестировать функцию внутри функционального компонента React с помощью jest.spyOn с библиотекой тестирования React

#javascript #reactjs #jestjs #react-testing-library

Вопрос:

Это простой компонент реакции. Я использую библиотеку тестирования React для компонентов модульного тестирования, и мне не удалось протестировать handleClick функцию TestComponent использования jest.spyOn() . Кто-нибудь может, пожалуйста, помочь?

Компонент

 import React from 'react';

const Button = (props) => (
  <button onClick={props.handleClick}> {props.text}</button>
);

const TestComponent = () => {
  const handleClick = () => {
    console.log('clicked!');
  };
  return (
    <div>
      <Button text="Test Button" handleClick={handleClick} />
    </div>
  );
};

export default TestComponent;
 

Тест

   it('expect spy to be called', () => {
    const { getByText } = render(<TestComponent />);
    
    const spy = jest.spyOn(TestComponent, 'handleClick');
    
    const button = getByText('Test Button');
    fireEvent.click(button);
    expect(spy).toHaveBeenCalled();
  });
 

Ошибка, которую я получаю, находится ниже. Я пробовал использовать TestComponent.prototype в jest.spyOn , но это тоже не помогает.

 Cannot spy the handleClick property because it is not a function; undefined given instead
 

Комментарии:

1. Короче говоря, вы захотите проверить результат вызова handleClick , не обязательно, что он был вызван. Например, при нажатии на кнопку должно произойти что-то с DOM/URL (отображается предупреждение, обновляется счетчик, в API был отправлен некоторый текст, URL-адрес был изменен и так далее). Опять же, проверьте результат, а не действие. Отдельно следует отметить, что вы не можете следить за выражением функции в функциональном компоненте, потому что оно не является свойством функции (короче говоря, TestComponent.handleClick не является функцией).

2. Если вы хотите узнать больше о наследовании прототипов (что не обязательно для создания/тестирования функциональных компонентов React), прочитайте эту статью MDN . Почти забыл: поскольку вы не обязательно обновляете DOM/URL, ваш тест должен сосредоточиться на утверждении, что console.log он был вызван с помощью «нажал» при нажатии кнопки… что требует насмешек console.log .

Ответ №1:

Вы не можете шпионить handleClick за обработчиком событий, так как он определен в функциональной области, он закрытый.

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

Но в вашем примере обработчик handleClick событий ничего не делает, просто вызывает console.log , тогда вы можете только утверждать , вызывается ли console.log вызываемое, косвенно утверждать, вызывается ли handleclick вызываемое.

 // arrange
const logSpy = jest.spyOn(console, 'log')
// act
// ...
// assert
expect(logSpy).toHaveBeenCalled()