How do I test with jest whether this api middleware handles errors thrown by fetch?

I have the following api middleware in my react/redux app, which I'm unittesting with jest. The module code is:

// ./src/middleware/api.js

import fetch from 'isomorphic-fetch';

// Checks if the returned statuscode is in the successful range
const handleErrors = (response) => {
  if (!response.ok) {
    throw Error(response.statusText);
  }
  return response;
};

export const get = (endpoint) => {
  const options = { credentials: 'include', method: 'GET' };

  return fetch(endpoint, options)
    .then(handleErrors)
    .then(response => response.json())
    .catch(error => error.message);
};

And the test is:

// ./src/middleware/__tests__/api.test.js

import fetch from 'isomorphic-fetch';
import { get } from '../api';

// Mock calls to fetch by the api middleware
// loads https://github.com/jefflau/jest-fetch-mock instead of fetch
jest.mock('isomorphic-fetch');

describe('api middleware', () => {
  describe('get', () => {
    it('should return the response on success', () => {
      const expected = { data: ['data'], meta: {} };
      const body = JSON.stringify(expected);
      const init = { status: 200, statusText: 'OK' };

      fetch.mockResponseOnce(body, init);

      return get('http://endpoint').then(actual => expect(actual).toEqual(expected));
    });

    it('should return the statusText for unsuccessful status codes', () => {
      const expected = 'Unauthorized';
      const body = JSON.stringify({ errors: ['You are not logged in'] });
      const init = { status: 401, statusText: expected };

      fetch.mockResponseOnce(body, init);

      return get('http://endpoint').then(actual => expect(actual).toEqual(expected));
    });

    // I have not been able to mock this so far    
    it('handles fetch errors', () => {
      return get('doesnotexist').then(actual => expect(actual).toEqual(false));
    });
  });
});

In the last assertion i want to test whether it catches errors thrown by fetch (so when there is no network connection for example). But I'm having trouble testing that. I'm not sure how I'd simulate an error in fetch and then test for it. Does anyone know how I would go about mocking the last assertion?

Upvotes: 0

Views: 1965

Answers (2)

Mark Galloway
Mark Galloway

Reputation: 4151

If you give it an invalid body it will trip the catch portion of your promise.

fetch.mockResponseOnce(null, init);

Upvotes: 0

grgmo
grgmo

Reputation: 1015

By looking at the implementation of jest-fetch-mock it always resolves the promise, meaning your fetch will never go to catch. So you need to have a Promise.reject() and in your test you will need to do something like -

it('handles fetch errors', () => {
  return get('doesnotexist')
    .catch(error => expect(error).toEqual('some error'));
});

Upvotes: 3

Related Questions