React Hooks Testing Library 主要提供三個方法:renderHook
、act
、cleanup
。
使用
不要使用
如果要取得 hook 的回傳值,可透過result.current
取得當前最新的值。
當 hook 內部 state 改變時(例如,setXXX),需要把這個方法包在 act 後才加以呼叫。
用來清理測試環境,用法cleanup()
。
測試useUIState
的初始狀態
和狀態更新
時,是否都可正常工作。
以下測試三種狀態pageFlow
、isLoading
、isPending
。
// useUIState.js
import { useReducer } from 'react'
// 定義操作類型
const ACTIONS = {
SET_PAGE_FLOW: 'SET_PAGE_FLOW',
SET_IS_LOADING: 'SET_IS_LOADING',
SET_IS_PENDING: 'SET_IS_PENDING'
}
// 初始化狀態
const getInitState = props => {
const {
match: { params: { phase } }
} = props
return {
pageFlow: phase,
isLoading: false,
isPending: false
}
}
// 自定義 Hook
const useUIState = props => {
const reducer = (state, action) => {
const { type, payload } = action
switch (type) {
case ACTIONS.SET_PAGE_FLOW:
return { ...state, pageFlow: payload }
case ACTIONS.SET_IS_LOADING:
return { ...state, isLoading: payload }
case ACTIONS.SET_IS_PENDING:
return { ...state, isPending: payload }
default:
return state
}
}
// 使用 useReducer 管理狀態
const [state, dispatch] = useReducer(reducer, props, getInitState)
// dispatch 觸發狀態更新操作
const setPageFlow = pageFlow => dispatch({
type: ACTIONS.SET_PAGE_FLOW,
payload: pageFlow
})
const setIsLoading = isLoading => dispatch({
type: ACTIONS.SET_IS_LOADING,
payload: isLoading
})
const setIsPending = isPending => dispatch({
type: ACTIONS.SET_IS_PENDING,
payload: isPending
})
const actions = {
setPageFlow,
setIsLoading,
setIsPending
}
return { state, actions }
}
export default useUIState
可以看到第一個check initial state
測試,假設renderHook
取得props
回傳值,並確認result.current.state
是跟預期initialState
相同。
而第二個test actions works
測試,透過act
模擬更新狀態,最後檢查當前狀態是否跟updatedState
相同。
// useUIState.test.js
import { renderHook, act } from '@testing-library/react-hooks'
import useUIState from './useUIState'
// flowTypes
export const PAGE_FLOW = {
INITIAL: 'initial',
EDIT: 'edit',
CONFIRM: 'confirm',
SUCCESS: 'success',
ERROR: 'error'
}
describe('useUIState', () => {
const props = {
match: { params: { phase: PAGE_FLOW.INITIAL } }
}
it('check initial state', () => {
const { result } = renderHook(() => useUIState(props))
const initialState = {
pageFlow: PAGE_FLOW.INITIAL,
isLoading: false,
isPending: false
}
expect(result.current.state).toEqual(initialState)
})
it('test actions works', () => {
const { result } = renderHook(() => useUIState(props))
const updatedState = {
pageFlow: PAGE_FLOW.ERROR,
isLoading: true,
isPending: true
}
act(() => {
result.current.actions.setIsLoading(updatedState.isLoading)
result.current.actions.setIsPending(updatedState.isPending)
result.current.actions.setPageFlow(updatedState.pageFlow)
})
expect(result.current.state).toEqual(updatedState)
})
})
以上是我在工作期間整理react-hooks-testing-library
幾個基本用法,如果需更深入了解可到官方文件學習。