JChao
JChao

Reputation: 2319

Jest test mock -- mock fetch inside another function

I have a stateful component I'm trying to test. This component serves as an intermediate step before it calls my other function. Kinda works like this

class MyList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      items: []
    };
  }

  componentDidMount() {
    this.props.loadMystuff().then(() => {
      if (this.state.eKey !== this.props.eKey) {
        let eKey = this.props.eKey;
        this.fetchSList(eKey);
      }
    }).catch((error) => toast(error.message));
  }

  fetchSList(eKey) {
    if (eKey !== '') {
      fetch(`some_api_url_config/${this.props.entityKey}`)
            .then(res => res.json())
            .then(
              (result) => {
                this.setState({
                  isLoaded: true,
                  items: result
              });
            },
            (error) => {
              this.setState({
                isLoaded: true,
                error
              });
            }
          );
    }
  }

  render() {
    const { error, isLoaded, items } = this.state;

    if (items) {
      return (
        <div>
          <h3>S List</h3>
          <ul>
            {items.map(item => (
              <li key={item}>
                {item}
              </li>
              ))}
          </ul>
        </div>
      );
    } else if (error) {
      return <div>Error: List Missing...{error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading List...</div>;
    } else {
        return <div>Not Found</div>;
    }
  }
}

the loadMystuff essentially gives me an eKey which I can use to call fetchSList, which calls fetch

I want to mock fetch and make it return an array of strings, but I haven't had any luck achieving that.

My test script looks like

describe(<MyList />, () => {
    let wrapper;
    let eKey = 'some_str';
    it("should have some listed items", () => {
        wrapper = shallow(<MyList loadMystuff={loadMystuff()}
                                       eKey={eKey}/>
        );
        expect(wrapper.find("div").find("ul").find("li").length).toBeGreaterThan(0);
})
)

How do I make the fetch command return an array like ['abc', 'def', 'ghi']?

EDIT:

after reading https://medium.com/@ferrannp/unit-testing-with-jest-redux-async-actions-fetch-9054ca28cdcd

I have come up with

it("should have some listed items", () => {
        window.fetch = jest.fn().mockImplementation(() =>
            Promise.resolve(mockResponse(200, null, '["abc", "def"]')));
        return store.dispatch(MyList(loadMystuff=loadMystuff(), eKey=eKey))
            .then(() => {
                const expectedActions = store.getActions();
                console.log('expectedActions', expectedActions);
            });
        })

but this doesn't seem to work

EDIT2:

I'm now investigating fetch-mock package.

My function is still fetchSList where there's a fetch in it. I'm running the test as

let eKey = 'some_key';

describe(<MyList />, () => {
    fetchMock.get('*', '["abc", "def"]');
    it("should have some listed items", () => {
        wrapper = shallow(<MyList loadMyStuff={loadMyStuff()}
                                       eKey={eKey}/>
        );
    expect(wrapper.find("div").find("ul").find("li")).toBe('something_something');

and it's returning an object instead of some form of string. jest is nice enough to print out what's in the object and there's nothing I expect, which is ["abc", "def"]

Upvotes: 2

Views: 1292

Answers (1)

Code-Apprentice
Code-Apprentice

Reputation: 83527

You can mock the responses for HTTP requests with a library such as nock or fetch-mock.

Upvotes: 3

Related Questions