Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何用酶测试自定义useFetch钩子_Reactjs_Unit Testing_Jestjs_Enzyme_React Hooks - Fatal编程技术网

Reactjs 如何用酶测试自定义useFetch钩子

Reactjs 如何用酶测试自定义useFetch钩子,reactjs,unit-testing,jestjs,enzyme,react-hooks,Reactjs,Unit Testing,Jestjs,Enzyme,React Hooks,那里 我这里有一个useFetch,它将使用useReducer触发组件的状态更改两次 type AsyncType = 'INIT' | 'PENDING' | 'RESOLVED' | 'REJECTED' | 'REDIRECTED' type AsyncAction = | { type: 'PENDING' } | { type: 'RESOLVED'; data: any } | { type: 'REJECTED'; error: Error } | { type

那里

我这里有一个useFetch,它将使用useReducer触发组件的状态更改两次

type AsyncType = 'INIT' | 'PENDING' | 'RESOLVED' | 'REJECTED' | 'REDIRECTED'

type AsyncAction =
  | { type: 'PENDING' }
  | { type: 'RESOLVED'; data: any }
  | { type: 'REJECTED'; error: Error }
  | { type: 'REDIRECTED' }

interface AsyncState {
  data?: any
  error?: Error
  type: AsyncType
}

const dataFetchReducer = (
  state: AsyncState,
  action: AsyncAction
): AsyncState => {
  switch (action.type) {
    case 'PENDING':
      return {
        ...state,
        type: 'PENDING',
      }
    case 'RESOLVED':
      return {
        ...state,
        type: 'RESOLVED',
        data: action.data,
      }
    // We can choose to ignore it, retry it or throw it to let the error boundary to catch it.
    case 'REJECTED':
      return {
        ...state,
        type: 'REJECTED',
        error: action.error,
      }
    case 'REDIRECTED':
      return {
        ...state,
        type: 'REDIRECTED',
      }
    default:
      throw new Error()
  }
}

// We can ignore the input if we don't want it to fetch new data when the component just mounted
export const useFetch = (
  initialRequestConfig?: AxiosRequestConfig,
  initialData?: any
): [AsyncState, Dispatch<AxiosRequestConfig>] => {
  const [requestConfig, setRequestConfig] = useState(initialRequestConfig)

  const [state, dispatch] = useReducer<typeof dataFetchReducer>(
    dataFetchReducer,
    {
      type: 'INIT',
      data: initialData,
    }
  )

  useEffect(() => {
    if (!requestConfig) return
    let didCancel = false
    const fetchData = async () => {
      dispatch({ type: 'PENDING' })
      try {
        const result = await axios(requestConfig)
        if (!didCancel) {
          dispatch({ type: 'RESOLVED', data: result.data })
        }
      } catch (error) {
        if (!didCancel) {
          if (
            error.response &&
            error.response.data &&
            error.response.data.redirect
          ) {
            dispatch({ type: 'REDIRECTED' })
          } else {
            dispatch({ type: 'REJECTED', error })
          }
        }
      }
    }
    fetchData()
    return () => {
      didCancel = true
    }
  }, [requestConfig])
  return [state, setRequestConfig]
}
我试着像这样测试我的组件

export const PrivateRoute: FC<RouteProps> = ({
  component: Component,
  ...rest
}) => {
  const [state] = useFetch(api.getUser()) // the api with only return the axios config, like this: { method: "GET", url: '/user' }
  if (!Component) return null
  console.log(state)
  return (
    <Route
      {...rest}
      render={props =>
        state.type === 'PENDING' ? (
          <p>Loading</p>
        ) : state.type === 'RESOLVED' ? (
          <Component {...props} />
        ) : state.type === 'REJECTED' ? (
          <Error err={state.error} />
        ) : null
      }
    />
  )
}
import axios, { AxiosStatic } from 'axios'

interface AxiosMock extends AxiosStatic {
  mockResolvedValue: Function
  mockRejectedValue: Function
}

jest.mock('axios')
const mockedAxios = axios as AxiosMock
it('renders without crashing', async () => {
    const MockComp = () => <p>Test</p>
    mockedAxios.mockResolvedValue({ data: { user: 'caso' } })
    let wrapper
    await act(() => {
      wrapper = mount(
        <MemoryRouter initialEntries={['/random']}>
          <PrivateRoute path="/" component={MockComp} />
        </MemoryRouter>
      )
      wrapper.update() // wherever I put the update, the wrapper is always loading
    })
    console.log(wrapper.debug()) // this line will always be loading
    expect(wrapper.find(Route).prop('path')).toBe('/')
  })
it('renderingwithwithcrashing',async()=>{
常量MockComp=()=>测试

mockedAxios.mockResolvedValue({data:{user:'caso'}}) 让包装器 等待行动(()=>{ 包装=装载( ) wrapper.update()//无论我把更新放在哪里,包装器总是在加载 }) console.log(wrapper.debug())//将始终加载此行 expect(wrapper.find(Route.prop('path')).toBe('/')) })
总会有这样的警告
警告:测试中对PrivateRoute的更新未包装在act(…)中。


我不知道什么是测试它的正确方法。我花了两天的时间。有人知道什么是测试它的正确方法吗?我已经升级到react 16.9,我刚刚找到了最好的解决方案,我们可以使用jest模拟
useFetch
,我们只需返回模拟状态并测试渲染结果