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



我在测试我的组件时遇到问题,这些组件通过 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(typeof dispatch),然后单击按钮,输出显示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()
})
})

这是我的相关代码:

随机按钮.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

我的应用.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

我的函数.js

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

我的上下文.js

import React from 'react'
const MyContext = React.createContext({})
export default MyContext

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

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

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

测试实用程序.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钩子,但我相信这应该让你到一个好地方。

相关内容

最新更新