Диспетчеризация не является функцией - Библиотека React Testing с React Redux Hooks - PullRequest
0 голосов
/ 09 апреля 2020

Я хочу проверить, отправляет ли компонент действие в хранилище, для этого я должен высмеивать функции React Hooks.

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

Когда я запускаю свои тестовые наборы, даже если функция useDispatch является ложной, она возвращает ошибку, говорящую, что это не функция.

jest.mock('react-redux', () => ({
  useSelector: jest.fn(),
  useDispatch: jest.fn(() => {}),
}));

it('should be able open modal', () => {
  const { getByTestId } = render(<Dropdown />);

  fireEvent.click(getByTestId('dropdown'));
  fireEvent.click(getByTestId('button-Transactions'));

  const dispatch = jest.fn();
  useDispatch.mockReturnValue(dispatch);

  expect(dispatch).toHaveBeenCalledWith(openModal('transactions'));
});

Ошибка:

    TypeError: dispatch is not a function

      19 | 
      20 |     if (item.action) {
    > 21 |       dispatch(item.action);
         |       ^
      22 |     }
      23 | 
      24 |     return item;

Мой компонент:

const history = useHistory();
  const dispatch = useDispatch();

  function handleNavigation(item) {
    if (item.path) return history.push(item.path);

    if (item.action) {
      dispatch(item.action);
    }

    return item;
  }

Ответы [ 3 ]

0 голосов
/ 09 апреля 2020

Dispatch является компонентом функции более высокого порядка, в вашем случае вам нужно добавить функцию, которая будет называться


   function handleNavigation(item) {
     const { action, path} = item;
     if (path) return history.push(item.path);

    if (action) {
     dispatch(action()) // Added () ...
  }

   return item;

}

0 голосов
/ 09 апреля 2020

Компонент пытался выполнить функцию, которая еще не была объявлена. Нам нужно смоделировать перед методом рендеринга

const dispatch = jest.fn();
useDispatch.mockReturnValue(jest.fn());

const dropdown = render(<Dropdown />);
0 голосов
/ 09 апреля 2020

Это потому, что когда вы высмеивали его, вы не указали значение.

Я подумал о двух способах сделать это:

  1. Наличие реального хранилища в тесте , так что вы можете проверить интеграцию:
const mockedStore = { /* the things you need in store in your test */ };
const store = configureStore(mockedStore, browserHistory);

const { getByTestId } = render(<Provider store={store}><Dropdown /></Provider>);
Насмехайтесь над своим dispatch, но у вас останутся бесконечные проблемы с useSelector (особенно если у вас есть более одного useSelector в дереве, которое вы рендерили).
import * as ReactRedux from 'react-redux';

// useDispatch returns a function which we are mocking here
const mockDispatch = jest.fn();

beforeAll(() => {
  ReactRedux.useDispatch = jest.fn().mockImplementation(() => mockDispatch);
});

beforeEach(() => {
  ReactRedux.useDispatch.mockClear();
});


expect(mockDispatch).toHaveBeenCalledWith(yourAction);

Пожалуйста обратите внимание, что реальная проблема, с которой вы столкнетесь, связана не с отправкой, а с useSelector. Если вы будете издеваться над ним, он вернет значение, которое вы хотите. Но что если в вашем дереве их больше одного? для этого мне нужен настоящий магазин, насколько я знаю.

...