【问题标题】:How to test component callback invoked by child component callback in React with Enzyme?如何在 React with Enzyme 中测试子组件回调调用的组件回调?
【发布时间】:2017-01-26 21:24:54
【问题描述】:

假设我有以下应用程序:

class Child extends React.Component {
    render() {
        return <button onClick={this.handleChildOnClick}>{this.props.children}</button>;
    }

    handleChildOnClick() {
        this.props.onChildClick('foo');
    }
}

class Parent extends React.Component {
    render() {
        return <Child onChildClick={this.handleParentOnClick}>click me</Child>;
    }

    handleParentOnClick(text) {
        this.props.onParentClick(12345);
    }
}

class App extends React.Component {
    render() {
        return <Parent onParentClick={(num) => console.log(num)} />;
    }
}

我很难找出测试Parent 组件的正确方法。 ChildApp 不是问题,但 Parent...

我的意思是,我如何测试点击Child 组件是否会调用Parent 的点击回调,而无需:

  1. ...正在渲染ChildParent 应该作为浅渲染单独测试。 Child 也将单独测试,如果我进行装载渲染,我基本上是在两次测试 Child 上的点击回调。
  2. ...直接在Parent 实例上调用handleParentOnClick。为此,我不应该依赖 Parent 的确切实现。如果我更改回调函数的名称,测试将中断,很可能是误报。

还有第三种选择吗?

【问题讨论】:

    标签: unit-testing reactjs callback jestjs enzyme


    【解决方案1】:

    在测试Parent 时,您可以:

    import { shallow } from 'enzyme';
    import { stub } from 'sinon';
    
    describe('<Parent/>', () => {
      it('should handle a child click', () => {
        const onParentClick = stub();
        const wrapper = shallow(<Parent onParentClick={onParentClick} />);
        wrapper.find("Child").prop('onChildClick')('foo');
        expect(onParentClick.callCount).to.be.equal(1);
        // You can also check if the 'foo' argument was passed to onParentClick
      });
    });
    

    【讨论】:

    • Enzyme 的 find 方法接受 React 类作为选择器,因此您可能希望删除 Child 周围的引号(第 8 行)。除此之外,这几乎是我给出的答案
    • 这是我一直在寻找的答案,非常感谢 =) @JordanBonitatis 这将需要额外的导入,而引用示例则不需要。除了字符串更容易出错之外,将类与字符串作为选择器传递还有其他优势吗?
    • 在子类是 MaterialUI 组件的情况下,这对我不起作用。为什么会突然冒出任何想法?
    【解决方案2】:

    我想这可以给你一些想法。

    // 组件

    class Child extends React.Component {
      render() {
        return <button onClick={this.handleChildOnClick} className="t-btn">{this.props.children}</button>;
      }
      handleChildOnClick() {
        this.props.onChildClick('foo');
      }
    }
    

    // 测试

    import { spy, stub } from 'sinon';
    import { shallow } from 'enzyme';
    
    describe('Child Component', () => {
      it('should check handle click', () => {
        spy(Child.prototype, 'handleChildOnClick');
        const onChildClick = stub();
        const wrapper = shallow(<Child onChildClick={onChildClick}>);
        wrapper.find(".t-btn").simulate('click');
        expect(Child.prototype.handleChildOnClick.callCount).to.equal(1);
      });
    
      it('should check onChildClick', () => {
        const onChildClick = stub();
        const wrapper = shallow(<Child onChildClick={onChildClick}>);
        wrapper.find(".t-btn").simulate('click');
        expect(onChildClick.callCount).to.equal(1);
      });
    });
    

    用子组件测试父组件

    import { stub } from 'sinon';
    import { shallow } from 'enzyme';
    import Child from '../Components/Child';
    
    describe('Parent Component', () => {
      it('should check handle click', () => {
        const onParentClick = stub();
        const wrapper = shallow(<Parent onParentClick={onParentClick} />);
        wrapper.find(".t-btn").simulate('click');
        expect(Child.prototype.handleChildOnClick.callCount).to.equal(1);
      });
    
      it('should check onChildClick', () => {
        const onChildClick = stub();
        const wrapper = shallow(<Child onChildClick={onChildClick}>);
        wrapper.find(Child).prop('onChildClick')('foo');
        expect(onParentClick.callCount).to.be.equal(1);
      });
    });
    

    上面的代码只处理一个组件,但我希望这能给你一些要点。对不起,如果语法在任何地方都被破坏了..

    【讨论】:

    • 这不是我要找的答案...您只是在测试Child 组件,而不是Parent 组件(问题是关于)。不过感谢您的贡献。
    猜你喜欢
    • 2021-07-24
    • 1970-01-01
    • 2021-04-14
    • 2018-03-14
    • 1970-01-01
    • 2021-04-02
    • 2017-05-03
    • 2021-06-07
    • 2018-03-12
    相关资源
    最近更新 更多