score:3

Accepted answer

You don't need to mock the api call. fetch has its own library tests so you don't need to test if fetch works. But if you really need to test your method, you can just use jest - https://facebook.github.io/jest/docs/en/asynchronous.html . Forget the jest-fetch-mock. You can test:

  1. Was the method componentDidMount called?
  2. Was yourMethod called?
  3. After yourMethod finished, did the change occurred? (Your new state is the expected one?)

Just remember not to test the libraries themselves, or to go very deep into the component tree. You should only test atomically. One thing at a time.

Now:

You can use async/await or just test the fetch itself. First of all, you should abstract those fetch'es to their own methods. Now. If all you do is concatenate promises and if u get everything correctly u set the state, you just need to , on the test file, resolve that promise, and on its callback, check if the state changed to what you wanted.

Again, this has all you need to know: https://facebook.github.io/jest/docs/en/asynchronous.html#promises

And if you need one more resource here you go: https://codereviewvideos.com/course/react-redux-and-redux-saga-with-symfony-3/video/testing-javascript-s-fetch-with-jest-happy-path

score:0

The trick here is to assert state/snapshot after the data from remote source are received. Even with mocking it's still goes asynchronously. So you can use e.g. setTimeout to postpone assertion:

import React from "react";
import { shallow } from "enzyme";
import sinon from "sinon";
import fetch from "node-fetch";

sinon.stub(fetch, "Promise").returns(
  Promise.resolve({
    json: () => Promise.resolve( { name: "Hello" } )
  })
);


class Test extends React.Component {
  state = {
    name: "none"
  };
  async componentDidMount() {
    const res = await fetch( "https://swapi.co/api/people/1" ),
          data = await res.json();
    this.setState({ name: data.name });
  }
  render() {
    return <h1>{ this.state.name }</h1>;
  }
}

describe( "component with fetch", () => {
  test( "state gets updated with the fetch", ( done ) => {
    const wrapper = shallow( <Test /> );
    setTimeout(() => {
      wrapper.update();
      const state = wrapper.instance().state;
      console.log(state);
      done();
    }, 10 );
  });

});

score:0

We generally test the state that the lifecycle methods have changed by mocking the fetch calls. Avoid using setTimeout in tests as you never know how much time the fetchMock is gonna take, so you can use await instead of that. For example:

import React from "react";
import {shallow} from "enzyme";
import fetchMock from "fetch-mock";
import TestComponent from "./TestComponent";

describe(() => {
    it("should set the state after fetching data", () => {
        // arrange
        fetchMock.get(`https://www.example.com`, mockResponse);
        const wrapper = shallow(<TestComponent>);
        
        // act
        await wrapper.instance().componentDidMount();

        // assert
        expect(wrapper.state()).toEqual(newStateObject);

    })

})

Related Query

More Query from same tag