Ad

When Testing A React Component With Enzyme Is It Better To Use Simulate Or To Call The Method Directly On The Instance()?

- 1 answer

If you have a component like this

class Editor extends Component {
  handleChange() {
    // some code
  }

  render() {
     <div>
       <input className="Editor" onChange={this.handleChange} />
     </div>
  }
}

Is it better to test the handle change by simulating the change event with simulate like this:

wrapper.simulate('change', { // })

Or by calling the method directly by using instance:

wrapper.instance().handleChange()

Ad

Answer

If you are using Shallow Rendering then .simulate just tries to find the right prop and call it. From the Common Gotchas section for .simulate:

Even though the name would imply this simulates an actual event, .simulate() will in fact target the component's prop based on the event you give it. For example, .simulate('click') will actually get the onClick prop and call it.

There isn't any advantage to calling .simulate when using Shallow Rendering and simply calling the prop directly avoids issues caused by the event not mapping to the correct prop.


If you are using Full DOM Rendering then .simulatewill fire an event that ends up calling runEventsInBatch from the comically named ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Events.

So using .simulate with mount will actually simulate the event, just note from the Common Gotchas section that:

ReactWrapper will pass a SyntheticEvent object to the event handler in your code. Keep in mind that if the code you are testing uses properties that are not included in the SyntheticEvent, for instance event.target.value, you will need to provide a mock event...for it to work.

For Full DOM Rendering it is up to you to determine if there is any value in having ReactDOM simulate the event to call your handler or to just call your handler directly.


From this post by an Airbnb dev:

In general, I've found it's best to invoke the prop directly and avoid .simulate.

For your test it would look something like this:

test('onChange', () => {
  const wrapper = shallow(<Editor />);  // works with shallow or mount
  const onChangeHandler = wrapper.find('input').prop('onChange');
  // test onChangeHandler
})
Ad
source: stackoverflow.com
Ad