How to mock a React component lifecycle method wit

2019-03-21 02:52发布

问题:

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?

回答1:

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()
}


回答2:

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.