简体   繁体   English

开玩笑/酶测试:this.props.showOverlay不是函数

[英]jest/enzyme test: this.props.showOverlay is not a function

I have a small test that simulates a click (hoping to do more with the test, but this is where I'm stuck so far): 我有一个模拟点击的小型测试(希望对测试做更多的工作,但这是到目前为止的问题):

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');
});

When running this test, I get the error: 运行此测试时,出现错误:

TypeError: this.props.showOverlay is not a function TypeError:this.props.showOverlay不是一个函数

After doing some reading, I've realized that this isn't working because the simulated click calls a function that is two levels up from the component that is being tested ( HamburgerIcon ). 经过一番阅读之后,我意识到这是行不通的,因为模拟的点击会调用一个比正在测试的组件( HamburgerIcon )高两级的函数。

When I first tried to run this, I was using Enzyme's shallow , and I since changed it to mount thinking that this would give the test access to the showOverlay function, but I was wrong. 当我第一次尝试运行此函数时,我使用的是Enzyme的shallow ,后来我将其更改为mount以为这将使测试可以访问showOverlay函数,但我错了。

Then I read that this might be a good use case for a mock function , and I tried to start implementing this: 然后我读到,这可能是一个模拟函数的好用例,并且我尝试着开始实现这一点:

...

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');
});

This is where I am sort of lost -- I'm not sure if mock functions are the right direction here, and I'm also not sure how the syntax of setting up the mock function will work. 这就是我迷失的地方-我不确定模拟函数在这里是否是正确的方向,我也不确定设置模拟函数的语法将如何工作。

Continue with shallow if you're just unit testing a single component. 如果只是对单个组件进行单元测试,请继续shallow If this component is nested and you're testing against child nodes, then you'll mount the parent. 如果该组件是嵌套的,并且您正在针对子节点进行测试,则将mount父组件。

That said, you're on the right track for using a mock function. 就是说,您在使用模拟功能的正确道路上。 Simply pass it into the component like so: 只需将其传递到组件中即可,如下所示:

<HamburgerIcon showOverlay={showOverlay} />

For example: 例如:

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();
});

If you have multiple props, then I like to do something more declarative: 如果您有多个道具,那么我想做一些更具说明性的事情:

// 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
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM