【问题标题】:jest/enzyme test: this.props.showOverlay is not a function笑话/酶测试:this.props.showOverlay 不是函数
【发布时间】:2019-06-01 03:15:24
【问题描述】:

我有一个模拟点击的小测试(希望通过测试做更多的事情,但这是我目前卡住的地方):

import React from 'react';
import Enzyme, { mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import HamburgerIcon from './HamburgerIcon';

Enzyme.configure({ adapter: new Adapter() });

test('hamburger icon changes class and state on click', () => {
  const wrapper = mount(<HamburgerIcon />);
  const hamburgerIcon = wrapper.find('div#mobile-nav');

  hamburgerIcon.simulate('click');
});

运行此测试时,我收到错误:

TypeError: this.props.showOverlay 不是函数

在阅读了一些内容后,我意识到这不起作用,因为模拟点击调用了一个比正在测试的组件高两层的函数 (HamburgerIcon)。

当我第一次尝试运行它时,我使用的是 Enzyme 的 shallow,后来我将其更改为 mount,认为这将使测试访问 showOverlay 函数,但我错了。

然后我读到这可能是mock function 的一个很好的用例,我尝试开始实现它:

...

const showOverlay = jest.fn();
// how to set this.props.ShowOverlay to the const above??

test('has div with class .closed', () => {
  const wrapper = mount(<HamburgerIcon />);
  const hamburgerIcon = wrapper.find('div#mobile-nav');

  hamburgerIcon.simulate('click');
});

这就是我迷失的地方——我不确定模拟函数是否是正确的方向,我也不确定设置模拟函数的语法将如何工作。

【问题讨论】:

    标签: javascript reactjs unit-testing jestjs enzyme


    【解决方案1】:

    如果您只是对单个组件进行单元测试,请继续使用shallow。如果此组件是嵌套的并且您正在针对子节点进行测试,那么您将 mount 父节点。

    也就是说,您在使用模拟函数的道路上是正确的。只需将其传递给组件,如下所示:

    &lt;HamburgerIcon showOverlay={showOverlay} /&gt;

    例如:

    const showOverlay = jest.fn();
    
    test('shows an overlay', () => {
      const wrapper = mount(<HamburgerIcon showOverlay={showOverlay} />);
      const hamburgerIcon = wrapper.find('div#mobile-nav');
    
      hamburgerIcon.simulate('click');
      expect(showOverlay).toHaveBeenCalled();
    });
    

    如果你有多个道具,那么我喜欢做一些更具声明性的事情:

    // define props here if you want an easy way check if they've been 
    // called (since we're defining at the top-level, all tests have access
    // to this function)
    const showOverlay = jest.fn();
    
    // then include them in an "initialProps" object (you can also just define
    // them within this object as well, but you'll have to use 
    // "initialProps.nameOfFunction" to check if they're called -- kind of 
    // repetitive if you have a lot of props that you're checking against)
    const initialProps = {
      showOverlay,
      someOtherFunction: jest.fn()
    }
    
    // use the spread syntax to pass all the props in the "initialProps" object
    // to the component
    test('shows an overlay', () => {
      const wrapper = mount(<HamburgerIcon { ...initialProps } />);
      const hamburgerIcon = wrapper.find('div#mobile-nav');
    
      hamburgerIcon.simulate('click');
    
      expect(showOverlay).toHaveBeenCalled(); // here we can just use the mock function name
      expect(initialProps.someOtherFunction).toHaveBeenCalledTimes(0); // here we'll have to use "initialProps.property" because it has been scoped to the object
    });
    

    【讨论】:

      猜你喜欢
      • 2019-04-05
      • 1970-01-01
      • 1970-01-01
      • 2018-06-21
      • 2020-06-19
      • 2019-04-15
      • 2021-09-07
      • 2018-03-23
      • 2020-06-14
      相关资源
      最近更新 更多