javascript - 使用 useReducer/useContext 和 React-Testing-Library 时为 "TypeError: dispatch is not a function"

标签 javascript reactjs jestjs react-testing-library

我在测试通过 useReducer 和 React-testing-library 使用调度的组件时遇到问题。

我创建了一个不太复杂的示例来尝试简化正在发生的事情,但仍然存在相同的 dispatch is not a function 问题。当我运行测试时,我收到此错误:


      11 |         data-testid="jared-test-button"
      12 |         onClick={() => {
    > 13 |           dispatch({ type: 'SWITCH' })
         |           ^
      14 |         }}
      15 |       >
      16 |         Click Me

此外,如果我在 RandomButton 内执行 console.log(typeofdispatch),然后单击按钮,输出将显示 function .

这是有问题的测试。

import React from 'react'
import RandomButton from '../RandomButton'
import { render, fireEvent } from '@testing-library/react'

describe('Button Render', () => {
  it('click button', () => {
    const { getByTestId, queryByText } = render(<RandomButton />)

    expect(getByTestId('jared-test-button')).toBeInTheDocument()
    fireEvent.click(getByTestId('jared-test-button'))
    expect(queryByText('My name is frog')).toBeInTheDocument()
  })
})

这是我的相关代码:

RandomButton.js

import React, { useContext } from 'react'
import MyContext from 'contexts/MyContext'

const RandomButton = () => {
  const { dispatch } = useContext(MyContext)

  return (
    <div>
      <Button
        data-testid="jared-test-button"
        onClick={() => {
          dispatch({ type: 'SWITCH' })
        }}
      >
        Click Me
      </Button>
    </div>
  )
}

export default RandomButton

MyApp.js

import React, { useReducer } from 'react'
import {myreducer} from './MyFunctions'
import MyContext from 'contexts/MyContext'
import RandomButton from './RandomButton'

  const initialState = {
    blue: false,
  }
  const [{ blue },dispatch] = useReducer(myreducer, initialState)


return (
    <MyContext.Provider value={{ dispatch }}>
      <div>
            {blue && <div>My name is frog</div>}
            <RandomButton />
    </div>
    </MyContext.Provider>
)

export default MyApp

MyFunctions.js

export const myreducer = (state, action) => {
  switch (action.type) {
    case 'SWITCH':
      return { ...state, blue: !state.blue }
    default:
      return state
  }
}

MyContext.js

import React from 'react'

const MyContext = React.createContext({})

export default MyContext

这可能是我错过的一些愚蠢的东西,但在阅读文档并查看在线其他示例后,我没有看到解决方案。

最佳答案

我还没有使用react-testing-library测试过redux hooks,但我知道你必须为渲染函数提供一个包装器,为Provider提供调度函数。

这是我用来测试连接到 redux 存储的组件的示例:

testUtils.js

import React from 'react';
import { createStore } from 'redux';
import { render } from '@testing-library/react';
import { Provider } from 'react-redux';
import reducer from '../reducers';

// https://testing-library.com/docs/example-react-redux
export const renderWithRedux = (
  ui,
  { initialState, store = createStore(reducer, initialState) } = {},
  options,
) => ({
  ...render(<Provider store={store}>{ui}</Provider>, options),
  store,
});

所以,根据您分享的内容,我认为您想要的包装器看起来像这样:

import React from 'react';
import MyContext from 'contexts/MyContext';

// export so you can test that it was called with specific arguments
export dispatchMock = jest.fn();

export ProviderWrapper = ({ children }) => (
  // place your mock dispatch function in the provider
  <MyContext.Provider value={{ dispatch: dispatchMock }}>
    {children}
  </MyContext.Provider>
);

在您的测试中:

import React from 'react';
import RandomButton from '../RandomButton';
import { render, fireEvent } from '@testing-library/react';
import { ProviderWrapper, dispatchMock } from './testUtils';

describe('Button Render', () => {
  it('click button', () => {
    const { getByTestId, queryByText } = render(
      <RandomButton />,
      { wrapper: ProviderWrapper }, // Specify your wrapper here
    );

    expect(getByTestId('jared-test-button')).toBeInTheDocument();
    fireEvent.click(getByTestId('jared-test-button'));
    // expect(queryByText('My name is frog')).toBeInTheDocument(); // won't work since this text is part of the parent component

    // If you wanted to test that the dispatch was called correctly
    expect(dispatchMock).toHaveBeenCalledWith({ type: 'SWITCH' });
  })
})

就像我说的,我不必专门测试 redux hooks,但我相信这应该能让你到达一个好地方。

关于javascript - 使用 useReducer/useContext 和 React-Testing-Library 时为 "TypeError: dispatch is not a function",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59548409/

相关文章:

javascript - 从url获取字符串值

javascript - 如何将文件从 dropzone 上传到 cloudinary

javascript - 带有自定义标签的 Mapbox GL Popup 设置内容

node.js - 如何在测试套件中仅模拟一次函数?

javascript - 语法错误 : Cannot use import statement outside a module: when running Jest-expo tests

javascript - Gulp 失败并返回 Unhandled 'error' 事件

javascript - 如何在现有网站上添加 React Js?

reactjs - Storybook react native (IOS) - RangeError : Maximum call stack size exceeded (native stack depth)

reactjs - 使用默认值响应路由参数

javascript - '命令未找到 : jest'