How to simulate click event with mock function in enzyme and Jest?

18,428

The problem was that you were rendering the component first and then trying to mock the function, by that time, you already created a bounded copy, the solution then is to mock directly into the prototype.

import Adapter from 'enzyme-adapter-react-16'
import React, {Component} from 'react'
import {configure, mount} from 'enzyme'

configure({adapter: new Adapter()})

export default class Foo extends Component {
  btnClick() {
    console.log("hello...")
  }

  render() {
    return (
      <div>
        <h2>Hello</h2>
        <button
            id="btn"
            onClick={this.btnClick.bind(this)}
        >
          Click
        </button>
      </div>
    )
  }
}

it("must call the mock method with button click", () => {
    let spy =  jest.spyOn(Foo.prototype, 'btnClick')
      .mockImplementation(() => 8)

    const wrapper = mount(<Foo/>)
    const btn = wrapper.find("#btn")
    btn.simulate("click")

    expect(spy).toHaveBeenCalled()
})
Share:
18,428

Related videos on Youtube

manas
Author by

manas

Updated on June 04, 2022

Comments

  • manas
    manas almost 2 years

    I have foo component I want to simulate button click with a mock function

     export default class Foo extends Component {
            btnClick() {
                console.log("hello...");
            }
            render() {
                return (
                    <div>
                        <h2>Hello</h2>
                        <button onClick={this.btnClick.bind(this)} id="btn">Click</button>
                    </div>
                );
            }
        }
    

    My test code looks like following

     it("must call the mock method with button click", () => {
    
            const wrapper = mount(<Foo />);
            wrapper.instance().btnClick = jest.fn(() => {
                return 8;
            });
    
            wrapper.update();
    
            const btn = wrapper.find("#btn");
            btn.simulate("click");
    
            expect(wrapper.instance().btnClick).toHaveBeenCalled();
        })
    

    simulation of click event calls the components real method instead of calling the mock method.

    I know it can be done by passing mock function as props to the <Foo/> component.

    I want to know is there any other way to simulate click(i.e private to the component) with mock method.

  • manas
    manas over 5 years
    This did not work ended with error "Cannot spy the undefined property because it is not a function; undefined given instead",
  • manas
    manas over 5 years
    I think you have not given second parameters that is the method name as string to the spyOn
  • Alexandre Borela
    Alexandre Borela over 5 years
    Yes, I missed the method's name, sorry.
  • manas
    manas over 5 years
    I used the second parameter method's name 'btnClick' but that resulted in failure of test "Expected mock function to have been called, but it was not called.". The mock function has not been called
  • Alexandre Borela
    Alexandre Borela over 5 years
    Yeah, I missed the fact that you were rendering the component and the bind(this) created a copy of that method, by the time that happens, it's not possible to mock it anymore. The solution is to mock the prototype of the method. Updated the answer with the solution.
  • manas
    manas over 5 years
    Thanks, thats great !!! but why need wrapper.update() if we have added the mock function to its prototype.
  • Alexandre Borela
    Alexandre Borela over 5 years
    Yep, there's no need to call the updated there, I didn't sleep well today.
  • AKJ
    AKJ over 5 years
    HI, I have a similar problem, i followed the answer above, but i get this error: Expected mock function to have been called. Any idea what is going on why i cannot successfully create a mock function despite using a spyOn?
  • RtmY
    RtmY about 5 years
    Can you add a short description?
  • shan
    shan almost 4 years
    @AlexandreBorela instance can't be used when it is a stateless component. How would you tackle this same problem if it is an SFC?