如何在 Jest/Enzyme 中模拟 React 上下文?
How to mock React context in Jest/Enzyme?
我正在尝试学习如何使用 Jest/Enzyme,并且一直坚持为我的单元测试提供上下文分派功能。第一个状态上下文似乎有效,但调度函数的第二个状态上下文无效。
我知道我可以通过上下文将第二个参数传递给浅函数,但我也无法让它以这种方式工作。
错误:
FAIL src/components/SearchBar.test.js
SearchBar.jsx
× should show search bar (4 ms)
● SearchBar.jsx › should show search bar
TypeError: Cannot destructure property 'asyncReducer' of '(0 , _Provider.useCocktailDispatch)(...)' as it is undefined.
7 | const SearchBar = () => {
8 | const state = useCocktailState()
> 9 | const { asyncReducer, dispatch } = useCocktailDispatch()
| ^
10 | const [modalShow, setModalShow] = useState(false)
11 | const [searchTerm, setSearchTerm] = useState(state.searchTerm)
12 |
at SearchBar (src/components/SearchBar.jsx:9:13)
at ReactShallowRenderer.render (node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:829:32)
at renderElement (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:643:26)
at fn (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:707:46)
at withSetStateAllowed (node_modules/enzyme-adapter-utils/src/Utils.js:100:18)
at Object.render (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:707:20)
at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:411:22)
at shallow (node_modules/enzyme/src/shallow.js:10:10)
at Object.<anonymous> (src/components/SearchBar.test.js:13:25)
SearchBar.test.js 片段:
Enzyme.configure({adapter: new Adapter()})
jest.mock('../state-provider/Provider')
describe('SearchBar.jsx', () => {
it('should show search bar', () => {
// shallow renders react component to memory instead of DOM
// it wraps component in wrapper to give us functions to examine component
const wrapper = shallow(<SearchBar />) // <- line where error occurs
const searchBar = wrapper.find('InputGroup FormControl') // searchBar also a wrapper
expect(searchBar.exists()).toBe(true)
})
})
Provider.js:
import React, { useContext, useReducer } from 'react'
import { asyncReducer, reducer, initialState } from './reducer';
export const StateContext = React.createContext();
export const DispatchContext = React.createContext();
export const useCocktailState = () => {
const context = useContext(StateContext)
if (context === undefined) {
throw new Error(`useCocktailState must be used within a Provider`);
}
return context;
}
export const useCocktailDispatch = () => {
const context = useContext(DispatchContext)
if (context === undefined) {
throw new Error(`useDispatch must be used within a Provier`);
}
return context;
}
const Provider = ({children}) => {
const [state, dispatch] = useReducer(reducer, initialState)
return (
<DispatchContext.Provider value={{asyncReducer:asyncReducer(dispatch),dispatch}}>
<StateContext.Provider value={state}>
{children}
</StateContext.Provider>
</DispatchContext.Provider>
)
}
export default Provider
jest.mock('../state-provider/Provider', () => ({
useCocktailDispatch: () => ({
asyncReducer: //your implementation of mock method or jest.fn() for dummy one
dispatch: //your implementation of mock or jest.fn() for dummy one
})
}))
我正在尝试学习如何使用 Jest/Enzyme,并且一直坚持为我的单元测试提供上下文分派功能。第一个状态上下文似乎有效,但调度函数的第二个状态上下文无效。 我知道我可以通过上下文将第二个参数传递给浅函数,但我也无法让它以这种方式工作。
错误:
FAIL src/components/SearchBar.test.js
SearchBar.jsx
× should show search bar (4 ms)
● SearchBar.jsx › should show search bar
TypeError: Cannot destructure property 'asyncReducer' of '(0 , _Provider.useCocktailDispatch)(...)' as it is undefined.
7 | const SearchBar = () => {
8 | const state = useCocktailState()
> 9 | const { asyncReducer, dispatch } = useCocktailDispatch()
| ^
10 | const [modalShow, setModalShow] = useState(false)
11 | const [searchTerm, setSearchTerm] = useState(state.searchTerm)
12 |
at SearchBar (src/components/SearchBar.jsx:9:13)
at ReactShallowRenderer.render (node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:829:32)
at renderElement (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:643:26)
at fn (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:707:46)
at withSetStateAllowed (node_modules/enzyme-adapter-utils/src/Utils.js:100:18)
at Object.render (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:707:20)
at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:411:22)
at shallow (node_modules/enzyme/src/shallow.js:10:10)
at Object.<anonymous> (src/components/SearchBar.test.js:13:25)
SearchBar.test.js 片段:
Enzyme.configure({adapter: new Adapter()})
jest.mock('../state-provider/Provider')
describe('SearchBar.jsx', () => {
it('should show search bar', () => {
// shallow renders react component to memory instead of DOM
// it wraps component in wrapper to give us functions to examine component
const wrapper = shallow(<SearchBar />) // <- line where error occurs
const searchBar = wrapper.find('InputGroup FormControl') // searchBar also a wrapper
expect(searchBar.exists()).toBe(true)
})
})
Provider.js:
import React, { useContext, useReducer } from 'react'
import { asyncReducer, reducer, initialState } from './reducer';
export const StateContext = React.createContext();
export const DispatchContext = React.createContext();
export const useCocktailState = () => {
const context = useContext(StateContext)
if (context === undefined) {
throw new Error(`useCocktailState must be used within a Provider`);
}
return context;
}
export const useCocktailDispatch = () => {
const context = useContext(DispatchContext)
if (context === undefined) {
throw new Error(`useDispatch must be used within a Provier`);
}
return context;
}
const Provider = ({children}) => {
const [state, dispatch] = useReducer(reducer, initialState)
return (
<DispatchContext.Provider value={{asyncReducer:asyncReducer(dispatch),dispatch}}>
<StateContext.Provider value={state}>
{children}
</StateContext.Provider>
</DispatchContext.Provider>
)
}
export default Provider
jest.mock('../state-provider/Provider', () => ({
useCocktailDispatch: () => ({
asyncReducer: //your implementation of mock method or jest.fn() for dummy one
dispatch: //your implementation of mock or jest.fn() for dummy one
})
}))