Testing own custom React hook by using `@testing-library/react-hook` with Jest
Sometimes we create an own custom React hook for your own React application.And these hooks have a several fun […]
広告ここから
広告ここまで
目次
Sometimes we create an own custom React hook for your own React application.
And these hooks have a several functionality like handling state and dispatching Redux action and moe…
We can test these hooks using @testing-library/react-hook
.
Install
$ yarn add -D react-@testing-library/react-hooks react-test-renderer
Write a test for React hook
In this post, we make a test code for the example custom hook.
const useExampleModalHook = () => {
const [modal, modalOpen] = useState(false)
const open = useCallback(() => {
modalOpen(true)
}, [modalOpen])
const close = useCallback(() => {
modalOpen(false)
}, [modalOpen])
const toggle = useCallback(() => {
modalOpen(!modal)
}, [modal, modalOpen])
return {
modal,
open,
close,
toggle,
}
}
And this is a test code for the hook.
import { renderHook, act } from '@testing-library/react-hooks';
describe('useExampleModalHook', () => {
let result = renderHook(() => useExampleModalHook()).result
beforeEach(() => {
result = renderHook(() => useExampleModalHook()).result
})
afterEach(() => {
mockDispatch.mockClear();
});
it('should modal is false by default', () => {
expect(result.current.modal).toEqual(false)
})
it('should modal is true when call open', () => {
act(() => {
result.current.open()
})
expect(result.current.modal).toEqual(true)
})
it('should modal is true when called toggle once', () => {
act(() => {
result.current.toggle()
})
expect(result.current.modal).toEqual(true)
})
it('should modal is true when called toggle once', () => {
act(() => {
result.current.toggle()
})
act(() => {
result.current.toggle()
})
expect(result.current.modal).toEqual(false)
})
})
renderHook
will return own hook without creating any React Component.
And use act
, we can execute any hook function.
With Redux (useDispatch / useSelector)
If we want to test hook using Redux hooks, we need to mock by jest.
export const exampleHookWithRedux = () => {
const dispatch = useDispatch();
const globalClose = useCallback(() => {
dispatch(closeUserModal('username'));
}, [dispatch]);
return {
dummy: useSelector((state: State) => state.modal),
globalClose,
}
}
This is a test code for the hook.
const mockDispatch = jest.fn();
const mockSelector = jest.fn().mockImplementation(() => ({
status: '',
result: '',
}));
jest.mock('react-redux', () => ({
useDispatch: () => mockDispatch,
useSelector: () => mockSelector(),
}));
describe('exampleHookWithRedux ', () => {
let result = renderHook(() => exampleHookWithRedux ()).result
beforeEach(() => {
result = renderHook(() => exampleHookWithRedux ()).result
})
it('should modal is false by default', () => {
expect(result.current.dummy).toEqual({
status: '',
result: '',
})
})
it('should call dispatch function at once', () => {
act(() => {
result.current.globalClose()
})
expect(mockDispatch).toHaveBeenCalledTimes(1)
})
it('should call valid action', () => {
act(() => {
result.current.globalClose()
})
expect(mockDispatch).toHaveBeenCalledWith({
type: 'CLOSE_USER_MODAL',
payload: {
username: 'username'
}
})
})
it('When selector return updated value, should get updated one', () => {
mockSelector.mockImplementationOnce(() => ({
status: 'loading',
result: ''
}))
result = renderHook(() => exampleHookWithRedux ()).result
expect(result.current.dummy).toEqual({
status: 'loading',
result: '',
})
})
})