Awa Melvine
Awa Melvine

Reputation: 4087

Enzyme/Jest Class method spy not being called on input change

At first, I thought there was something wrong with other aspects of my code. So I created a new, simplified version of the component in a newly created project and wrote the test for it but my spy is still not being called.

Here's the component I'm testing:

import React from 'react';

class TextEditor extends React.Component {
  handleChange = (e) => {
    console.log({ value: e.target.value });
  }

  render() {
    return (
      <div>
        <input type="text" name="name" id="name" onChange={this.handleChange} />
      </div>
    );
  }
}

export default TextEditor;

And here is the unit test:

import React from 'react';
import { shallow } from 'enzyme';
import TextEditor from '../TextEditor';

describe('TextEditor', () => {
  it('handles change event', () => {
    const wrapper = shallow(<TextEditor />);
    const spy = jest.spyOn(wrapper.instance(), 'handleChange');
    wrapper.find('input').simulate('change', { target: { value: 'test value' }});
    expect(spy).toHaveBeenCalledTimes(1);
  });
});

The result of running the test: enter image description here

When I run this, it fails because the spy doesn't get called. But notice that the console.log statement in the handleChange function gets executed. So the test actually calls the function but the spy isn't recognized as having been called.

What could I be doing wrong? Thanks for your ideas.

Upvotes: 0

Views: 665

Answers (1)

Lin Du
Lin Du

Reputation: 102617

The handleChange method is class properties, not the instance method of the class.

If you insist to use class properties, you should call wrapper.instance().forceUpdate() after spying. See issue#365

E.g.

TextEditor.tsx:

import React from 'react';

class TextEditor extends React.Component {
  handleChange = (e) => {
    console.log({ value: e.target.value });
  };

  render() {
    return (
      <div>
        <input type="text" name="name" id="name" onChange={this.handleChange} />
      </div>
    );
  }
}

export default TextEditor;

TextEditor.test.tsx:

import { shallow } from 'enzyme';
import React from 'react';
import TextEditor from './TextEditor';

describe('TextEditor', () => {
  it('handles change event', () => {
    const wrapper = shallow(<TextEditor />);
    const spy = jest.spyOn(wrapper.instance(), 'handleChange');
    wrapper.instance().forceUpdate();
    wrapper.find('input').simulate('change', { target: { value: 'test value' } });
    expect(spy).toHaveBeenCalledTimes(1);
  });
});

Test result:

 PASS  examples/70652888/TextEditor.test.tsx (13.006 s)
  TextEditor
    ✓ handles change event (100 ms)

  console.log
    { value: 'test value' }

      at TextEditor.handleChange (examples/70652888/TextEditor.tsx:5:13)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        14.708 s

Also, see this answer

Upvotes: 1

Related Questions