如何测试反应挂钩方法?

时间:2019-10-20 19:35:39

标签: javascript reactjs testing jestjs

我正在使用玩笑/伊斯坦布尔来跟踪代码覆盖率。我有以下组件:

 // Menu.jsx    
  const myComponent = ({ initialState }) = {
        const [state, setState] = useState(initialState);
        const [menuContent, setMenuContent] = useState(undefined);

        return (
            <Menu>
                {state.accordions.map(item, index) => (
                    <MenuPanel id={item.id}>
                        {item.details && typeof item.details === 'function'
                            ? <item.details setContent={myContent => setMenuContent(myContent)} />
                            : undefined}
                    </MenuPanel>
                )}
            </Menu>
        )
    }

在我对Menu.jsx的测试中,笑话覆盖率报告抱怨setMenuContent未包含在我的测试中。我应该如何测试像这样的钩子?我以为不可能。我尝试测试setContent道具是否存在于子组件上,但这无济于事。关于如何使它通过覆盖率报告的任何想法?我在测试中使用浅层渲染。

1 个答案:

答案 0 :(得分:1)

您可以为该特定组件模拟useState,请尝试以下操作:

const stateMock = jest.fn();

jest.mock('react', () => {
  const ActualReact = require.requireActual('react');
  return {
    ...ActualReact,
    useState: () => ['value', stateMock], // what you want to return when useContext get fired goes here
  };
});

每次您的组件调用useState时,您的stateMock都会被解雇,案件也将得到赔偿

这只是您可以做什么的一个最小示例,但是您可以增强模拟功能以识别每个状态调用

如果要保留React状态的默认行为,可以在组件主体外部声明回调函数,在这种情况下,有关代码行如下:

<item.details setContent={myContent => setMenuContent(myContent)} />

因此,您可以将其从组件中取出并执行类似的操作,而不是使用此匿名函数始终可能导致内存泄漏:

   const setContent = (setMenuContent) => (myContent) => setMenuContent(myContent)


  const myComponent = ({ initialState }) = {
    const [state, setState] = useState(initialState);
    const [menuContent, setMenuContent] = useState(undefined);

    return (
        <Menu>
            {state.accordions.map(item, index) => (
                <MenuPanel id={item.id}>
                    {item.details && typeof item.details === 'function'
                        ? <item.details setContent={setContent(setMenuContent)} />
                        : undefined}
                </MenuPanel>
            )}
        </Menu>
    )
}

现在您可以导出此函数并用文本覆盖它,这将允许您模拟setMenuContent

export const setContent = (setMenuContent) => (myContent) => setMenuContent(myContent)

您的最后一个选择是使用诸如酶或react-testing-lib之类的东西,在dom中找到此item.details组件并触发点击操作