linuxNoob
linuxNoob

Reputation: 720

How to supply header when mocking fetch?

I am trying to mock the fetch call in my create-react app but the test fails since it doesn't match the required headers.

Here is my code under test:

 const serviceHeaders = {
    headers: {
      'CONSUMER.ID': process.env.REACT_APP_SERVICE_CONSUMER_ID,
      'SERVICE.NAME': process.env.REACT_APP_SERVICE_NAME,
      'SERVICE.ENV': "dev"
    }
  };

  const localhostURL = "http://localhost:8080";
 useEffect(() => {
    let itemURL = localhostURL + '/items/';
    fetch(itemURL, serviceHeaders).then(response => {
        if (response.ok) {
            response.json().then(data => {
                setItems(data);
            }).catch(error => {
                console.log("Successful request to retrieve items but could not parse body as json", error);
            })
        }
    });
});

and the test:

const fetchMock = jest.spyOn(window, 'fetch').mockImplementation(() => 
  Promise.resolve({ ok: true, json: () => Promise.resolve([{itemName: 'Color', itemId: 23},
  {itemName: 'Car', itemId: 34}])}));

const localhostURL = "http://localhost:8080";
act(() => { render(<ItemSelection/>) });

expect(fetchMock).toBeCalledWith(localhostURL + '/items/');

Is there a way to supply headers to spyOn() or is there another way to achieve it? I'm using jest and react-testing library.

Upvotes: 0

Views: 767

Answers (1)

tony g
tony g

Reputation: 412

Rather than mock fetch, I would use an HTTP interceptor like nock. That way you can test behavior vs testing implementation details. With an HTTP interceptor, you can reply based on specific headers too.

it('gives users options to choose from', async () => { // <-- notice async for server to respond
  const mockData = [
    {itemName: 'Color', itemId: 23},
    {itemName: 'Car', itemId: 34}
  ];
  nock(`${yoursite}`, {
      reqheaders: {
        'CONSUMER.ID': process.env.REACT_APP_SERVICE_CONSUMER_ID,
        'SERVICE.NAME': process.env.REACT_APP_SERVICE_NAME,
        'SERVICE.ENV': "dev"
      },
    })
    .get('/items')
    .reply(200, {data: mockData});
  
  const {queryAllByTestId} = render(<ItemSelection/>);
  await waitFor(() => expect(queryAllByTestId('item-option').length > 0).toBe(true)); // <-- Waiting for server to kick over
});

Upvotes: 1

Related Questions