调度不是函数-带有React Redux钩子的React Testing库

时间:2020-04-09 16:24:30

标签: javascript reactjs redux react-redux react-testing-library

我想测试组件是否正在向商店分派动作,为此,我必须模拟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 :(得分:2)

该组件正在尝试执行尚未声明的功能。 我们需要在render方法

之前进行模拟
const dispatch = jest.fn();
useDispatch.mockReturnValue(jest.fn());

const dropdown = render(<Dropdown />);

答案 1 :(得分:0)

这是因为在模拟它时,您没有指定值。

我想到了两种方法:

  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。 如果您对其进行模拟,它将返回您想要的值。但是,如果您的树上不止一个呢?为此,据我所知,我需要真正的商店。

答案 2 :(得分:0)

调度是高阶函数组件, 您需要添加一个名为

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

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

   return item;

}