Dispatch 不是一个函数 - 带有 React Redux Hooks 的 React 测试库

Dispatch is not a function - React Testing Library with React Redux Hooks

我想测试组件是否正在向商店发送操作,为此,我必须模拟 React Hooks 的功能。

我正在使用 useDispatch 挂钩获取调度程序函数并将其放入一个变量中以便我可以调用它。

当我 运行 我的测试服时,即使 useDispatch 函数被模拟,它 returns 一个错误说它不是一个函数。

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;
  }

因为你mock的时候没有指定值

我想到了两种方法:

  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>);
  1. 模拟你的 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。 如果你模拟它,它会 return 你想要的值。但是如果你的树中不止一个呢?为此,据我所知,我需要真正的商店。

该组件试图执行一个尚未声明的函数。 我们需要在渲染方法之前模拟

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

const dropdown = render(<Dropdown />);