J. Hesters
J. Hesters

Reputation: 14748

JavaScript (ES6) and fetch(): How can I throw an error so that catch triggers? (Testing it with Jest)

I thought I was decent at JavaScript until now. I want to write a helper function for my HTTP requests. I tested it with Jest. The problem is that the catch() part does not get triggered. Let me give you the test first:

it("recognizes when a response's status is not okay", () => {
  fetch.mockResponseOnce(JSON.stringify({ ok: false }));

  expect.assertions(1);

  return getRequestWithoutHeader(fullTestUrl).catch(err => {
    expect(err.ok).toEqual(false);
  });
});

Maybe the test is written wrongly which fails. Anyways here is the helper function that I did write. I tried out different implementations and they all fail the test:

// Implementation one: with throw
export const getRequestWithoutHeader = fullUrlRoute =>
  fetch(fullUrlRoute).then(response =>
    response.json().then(json => {
      if (!response.ok) {
        throw Error(json);
      }
      return json;
    }, error => error)
  );

// Implementation two: with throw new
export const getRequestWithoutHeader = fullUrlRoute =>
  fetch(fullUrlRoute).then(response =>
    response.json().then(json => {
      if (!response.ok) {
        throw new Error(json);
      }
      return json;
    }, error => error)
  );

// Implementation three: With Promise.reject
export const getRequestWithoutHeader = fullUrlRoute =>
  fetch(fullUrlRoute).then(response =>
    response.json().then(json => {
      if (!response.ok) {
        return Promise.reject(json);
      }
      return json;
    }, error => error)
  );

// Implementation four: with new Promise
export const getRequestWithoutHeader = fullUrlRoute =>
  new Promise((resolve, reject) => {
    fetch(fullUrlRoute).then(response =>
      response.json().then(
        json => {
          if (!response.ok) {
            reject(json);
          }
          resolve(json);
        },
        error => reject(error)
      )
    );
  });

None of these work. Some of these would return using a then in the test, but I want the promise to be thrown. I want to trigger a catch.

How do I have to write this helper function?

Upvotes: 0

Views: 843

Answers (2)

J. Hesters
J. Hesters

Reputation: 14748

Here is what I ended up having to do:

I used jest-fetch-mock for mocking the requests.

In order for the promise to be correctly rejected, I had to overrite the init argument of the mockResponseOnce function.

Here is how the test ended up looking:

  it("recognizes when a response's status is not okay", () => {
    fetch.mockResponseOnce(JSON.stringify({ someResponse: "someResponse" }), { status: 403 });
    expect.assertions(1);

    return getRequestWithHeader(fullTestUrl, article).catch(err => {
      expect(err.someResponse).toEqual("someResponse");
    });
  });

By setting the status explicitly, it automatically sets ok: false in the response, triggering the function.

I also applied CertainPerfomance's tips and refactored the function like this:

export const getRequestWithoutHeader = fullUrlRoute =>
  fetch(fullUrlRoute)
    .then(response => {
      if (!response.ok) {
        return Promise.reject(response);
      }
      return response.json();
    })

Upvotes: 0

Suban Dhyako
Suban Dhyako

Reputation: 2526

you can try like this

  fetch(fullUrlRoute)
  .then(response =>{
      if (response.ok) {
        return response.json();
      }
      else throw response
  })
  .then(json=> {
      console.log(json);
    })
  .catch(error =>{
      console.log(error)
   });

Hope this help you

Upvotes: 1

Related Questions