Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock a React component lifecycle method with Jest and Enzyme?

The Enzyme docs for Full DOM Rendering here contains the following example of spying on a lifecycle method with Sinon:

describe('<Foo />', () => {

  it('calls componentDidMount', () => {
    sinon.spy(Foo.prototype, 'componentDidMount');
    const wrapper = mount(<Foo />);
    expect(Foo.prototype.componentDidMount.calledOnce).to.equal(true);
  });
});

What is the equivalent to this using mock functions from Jest?

I'm using Create-React-App, and would rather not include Sinon if the same can be achieved with Jest.

Here's what I'd expect the test to look like:

describe('<App />', () => {

  it('calls componentDidMount', () => {
    jest.fn(App.prototype, 'componentDidMount');
    const wrapper = mount(<App />);
    expect(App.prototype.componentDidMount.mock.calls.length).toBe(1);
  });
});

In this case, App.prototype.componentDidMount doesn't reference the same function spy as it would do with Sinon.

The Jest docs on how mock functions actually work are a bit limited. I've followed the discussion here around what jest.fn() is doing, but it seems it's not really equivalent to sinon.spy().

How can I replicate that test with Jest?

like image 638
Lewis Avatar asked Jan 04 '17 10:01

Lewis


People also ask

Can you please explain React components lifecycle?

Lifecycle of ComponentsEach component in React has a lifecycle which you can monitor and manipulate during its three main phases. The three phases are: Mounting, Updating, and Unmounting.


2 Answers

This will not work with jest this way as jest.fn only have a parameter for the implementation. But more important, you should not spy on the internals of the object you want to test. You should think of Foo as a black box where you can put some properties in and get some stuff rendered back. Then you realize that there is no need to test that internal functions of Foo, like componentDidMount, get called. The only thing that matters is the output of the black box.

But if you really want do test it anyway:

const spy = jest.fn()
const componentDidMount = Foo.prototype.componentDidMount
Foo.prototype.componentDidMount = function(){
  spy()
  componentDidMount()
}
like image 153
Andreas Köberle Avatar answered Oct 27 '22 03:10

Andreas Köberle


As of Jest 19, you can do this:

describe('<App />', () => {
  it('calls componentDidMount', () => {
    const spy = jest.spyOn(App.prototype, 'componentDidMount');
    const wrapper = mount(<App />);
    expect(spy).toHaveBeenCalled();
    spy.mockReset();
    spy.mockRestore();
  });
});

jest.spyOn returns a mock function with all the normally available methods such as mockClear, mockReset and mockRestore.

Make sure to set up your spy before you mount with enzyme or create with react-test-renderer so that the created instance has a reference to the mocked function being spied on.

like image 6
Ryan H. Avatar answered Oct 27 '22 01:10

Ryan H.