问题是我们的 Jest 在 jsdom 中运行并且已经很旧了,但最终每当我编写如下所示的函数时,当我尝试在组件中使用它时,Jest 无法处理它。加载状态保持不变。当我将其包装在
console.logs
中时,我看到表状态从未更新,加载保持不变。
就像我必须模拟 tableState/Dispatch,但它是正在测试的组件的内部,因此无法在不被迫从视图中解除数据关联的情况下发送模拟。这对于延迟加载和道具传递问题可能会有点适得其反,所以尽量避免提起钩子。
const useTableDataBackend = (
dataInit,
RequestHandler = (OnSuccess, onError) => {},
MutationHandler = (data, timezone) => {}
) => {
const [tableState, tableDispatch] = useReducer(dataInit)
const { headers, filters, rowsPerPage, currentPage } = tableState
const getPageRequestHandler = (resetPage = true) => {
tableDispatch({ type: 'SET_LOADING', payload: true })
RequestHandler(
(data) => {
tableDispatch({ type: 'SET_LOADING', payload: false })
},
() => {
tableDispatch({ type: 'SET_LOADING', payload: false })
}
)
useEffect(() => {
tableDispatch({ type: 'SET_DATA', payload: dataInit })
tableDispatch({ type: 'SET_DATA_PAGINATED', payload: dataInit })
}, [dataInit])
useEffect(() => {
getPageRequestHandler(false)
}, [currentPage])
}
使用案例:
const myComponent = () => {
const RequestHandler = () => {
// Implementation here
}
const MutationHandler = () => {
// Implementation here
}
const { tableState, tableDispatch } = useTableDataBackend(
MutationHandler(RequestHandler()),
RequestHandler,
MutationHandler
)
return (
<div>{tableState}</div>
)
}
测试用例:
jest.mock(
'RequestHandler',
() => jest.fn()
)
it('should paginate correctly onClick of each control', () => {
RequestHandler.mockImplementationOnce(
(OnSuccess, onError) => {
//const data = Array.from({ length: 5 }, () => EncountersGetRequestHandlerSampleData.items.data[0])
onSuccess(data)
}
)
render(<myComponent />)
// Expect loading to stop but never does, can't test a disabled paginator
})
您的问题在这里:
RequestHandler.mockImplementationOnce(
(OnSuccess, onError) => {
//const data = Array.from({ length: 5 }, () => EncountersGetRequestHandlerSampleData.items.data[0])
onSuccess(data)
}
)
更改为:
RequestHandler.mockImplementation(
(OnSuccess, onError) => {
//const data = Array.from({ length: 5 }, () => EncountersGetRequestHandlerSampleData.items.data[0])
onSuccess(data)
}
)
如果被模拟的函数需要多次调用才能达到预期状态,mockImplementationOnce 显然不起作用。
即使在初始化像后端自定义分页这样复杂的东西时,请求也可能会在设置过滤器变量等时发生。也许这并不理想,该函数实际上应该只被调用一次,因此测试可能在 init 上发现了一些东西,但这仍然是必要的。
学到的教训:除了对使用带有状态和ajax的自定义钩子的组件进行初始化动态测试之外,任何其他操作都需要mockImplementation,而不是mockImplementationOnce。