使用 Jest 和酶时如何在 React.useEffect 钩子上获得线路覆盖?

Posted

技术标签:

【中文标题】使用 Jest 和酶时如何在 React.useEffect 钩子上获得线路覆盖?【英文标题】:How to get line coverage on React.useEffect hook when using Jest and enzyme? 【发布时间】:2020-03-17 22:46:24 【问题描述】:

使用 React、酶和玩笑,我如何在 useEffect() 内的 closeDrawer() 回调道具上获得代码覆盖率

import React, useEffect from 'react';
import Button from './button';

const DrawerClose = (closeDrawer) => 
  useEffect(() => 
    const handleEsc = (e: any) => 
      if (e.key === 'Escape') 
        closeDrawer();
      
    ;
    window.addEventListener('keyup', handleEsc);
    return () => window.removeEventListener('keyup', handleEsc);
  );
  return (
    <Button>
      close
    </Button>
  );
;

export DrawerClose;

测试:

import React from 'react';
import DrawerClose as Block from './drawer-close';

describe(`$Block.name`, () => 
  it('should have drawer open', () => 
    const wrapper = shallow(<Block closeDrawer=() => 'closed' />);
    expect(wrapper).toMatchSnapshot(); // will not hit the useEffect
  );
);

【问题讨论】:

【参考方案1】:

shallow() 还没有调用useEffect。它是 known issue #2086 并且是因为 React 的浅渲染器而发生的。

您可以使用mount() 并完全渲染或模拟每个/某些嵌套组件并仍然使用mount(),但结果更像shallow() 可以。比如:

jest.mock('../../Button.jsx', (props) => <span ...props />);

至于测试本身,您需要确保在点击 ESC 时会调用closeDrawer。所以我们需要使用spy来模拟模拟按ESC

const closeDrawerSpy = jest.fn();
const wrapper = mount(<Block closeDrawer=closeDrawerSpy />);
// simulate ESC pressing

至于模拟在window上按下的ESC,我不确定jest-dom是否允许,你可以试试(取自Simulate keydown on document for JEST unit testing)

var event = new KeyboardEvent('keyup', 'keyCode': 27);
window.dispatchEvent(event);

如果这不起作用(window.dispatchEvent is not a function 或类似的东西)你总是can mock addEventListener 可以直接访问处理程序。

【讨论】:

以上是关于使用 Jest 和酶时如何在 React.useEffect 钩子上获得线路覆盖?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jest 和酶测试 onClick() 函数和 useState 钩子

如何在构造函数内部使用上下文的情况下使用 jest 和酶来测试反应上下文?

Jest和酶有啥区别?

带有笑话和酶的反应单元测试

TypeError:使用 react-create-app jest 和酶进行测试时,调度不是函数

如何使用 Jest 在我的测试文件中获取 window.location.pathname?