React Hooks 3 - Test Hooks

Test React Hooks

I invested some time into hooks recently, this is sth I want to share: People says, use custom hooks, it can extract same functionality out as composable logic, so that the logic is more maintainable and testable,but then I found to test it, you will always need to create and mount a Component over it, because hooks behavior happens ONLY in react component in the vdom. I would say it is testable, but still a bit painful.

So here are 2 snippets I found that can be a conventions we used to test a custom hook:‌

I. With Customed Component, and simply get things from wrapper.prop

it('get same value when using `useMemo` and rerender with same prop in dependencies', () => {
    function Child() {
        return false;
    }
    function ComponentUsingMemoHook(props) {
        const { count } = props;
        const memoized = useMemo(() => ({ result: count * 2 }), [count]);
        return (<Child memoized={memoized} />);
    }
    const wrapper = mount(<ComponentUsingMemoHook count={1} />);
    const initialValue = wrapper.find(Child).prop('memoized');
    wrapper.setProps({ unRelatedProp: '123' });
    const nextValue = wrapper.find(Child).prop('memoized');
    expect(initialValue).to.equal(nextValue);
});

it('get different value when using `useMemo` and rerender with different prop in dependencies', () => {
    function Child() {
        return false;
    }
    function ComponentUsingMemoHook(props) {
        const { count, relatedProp } = props;
        const memoized = useMemo(() => ({ result: count * 2 }), [count, relatedProp]);
        return (<Child memoized={memoized} relatedProp={relatedProp} />);
    }
    const wrapper = mount(<ComponentUsingMemoHook relatedProp="456" count={1} />);
    const initialValue = wrapper.find(Child).prop('memoized');
    wrapper.setProps({ relatedProp: '123' });
    const nextValue = wrapper.find(Child).prop('memoized');
    expect(initialValue).to.not.equal(nextValue);
});

Ref : https://github.com/airbnb/enzyme/pull/2144/files#diff-fadeaaf857f5b3fe6522e89a63ca9a41​‌

II. Use react-test-hooks lib, (Requiring React 16.8 cos it uses <Suspense/>)

const { result } = renderHook(() => useTime(100));       
expect(result.current).toBe('mockNow');

Ref : https://www.newline.co/@jamesfulford/testing-custom-react-hooks-with-jest--8372a502​‌

A practice from downshiftjs

  • Get a folder/file structure for each complex hook

  • Use a testUtil to set up rendering a test component (as always)

  • Focus on testing hooks funtionality in test.spec.js

Ref : https://github.com/downshift-js/downshift/blob/v4.0.8/src/hooks/useSelect/testUtils.js, https://github.com/downshift-js/downshift/blob/v4.0.8/src/hooks/useSelect/__tests__/getLabelProps.test.js

Last updated