Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock child component in React

Is there a clean way to be able to mock a child element when unit testing an element, using Mocha and friends?

For example, say I have something like this:

<Parent>
  <Child aProp={ this.props.clickChild() }/>
</Parent>

I want to mock it so I can manually trigger aProp and then tell that it called the clickChild that I passed it.

like image 593
samanime Avatar asked Mar 17 '26 05:03

samanime


1 Answers

After lots of research, it looks like this isn't really possible. If you do them in a very specific format, you can use certain mocking things, but you have to do several things which would be non-standard in your "real" code. I'm not a fan of modifying code for tests.

An alternative that I've settled on is for certain cases, I would just find the element after a mount(), get the property that provides the callback, and then trigger that directly and do whatever I need. Not a perfectly universal scenario, but it works.

Take this example code:

// Parent.js
export default class Parent extends React.Component {
    doSomething() {
        this.props.doSomethingTriggered();
    }

    render() {
        return <div>
            <Child onClick={ this.doSomething.bind() }/>
        </div>;
    }
}

I can use enzyme to mount the component, then trigger the onClick property of Child and spy on the callback I gave it to ensure it was called properly.

 it('should do something', () => {
      const callback = sinon.spy(() => {});
      const wrapper = mount(<Parent doSomethingTriggered={ callback }/>);
      wrapper.find(Child).props().onClick();
      sinon.assert.calledOnce(callback);
 });

Not quite mocking, but does let me bypass a good chunk of dependent code in certain scenarios.


Since this is a popular question, an update for Enzyme 16, it is now possible. You can now call instance() on any element and then call its function directly.

For example, take these examples:

class Parent extends React.Component {
  render() {
    return <div><Child /></div>
  }
}

class Child extends React.Component {
  render() { return <div>Hi</div> }

  doSomething() { }
}

With Enzyme 16, you can now do:

mount(<Parent />).find(Child).instance().doSomething()
like image 196
samanime Avatar answered Mar 19 '26 19:03

samanime



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!