Search code examples
javascripttestingaxiosweb-api-testing

Testing 400 status code axios throws error


I'm creating an api test framework for a project I am working on and I'm looking to validate required fields in JSON objects being sent to an endpoint.

I'm trying to send a JSON object with a missing field and expecting a 400 response from my application with a validation message. But when making this call with axios it (somewhat rightly) throws an error as it received the 400.

I want to be able to assert that 400 is expected and to assert on the validation message.

All the examples I've come across are all regarding dealing with the 400 response in the correct way you would if you are not expecting the 400 response, but i am expecting it.

I couldn't seem to find anyone else trying this.

async function createReminder(reminderObject) {
  const response = await axios.post(`${config.get('baseUrl')}/reminder`, {
    ...reminderObject
  });

  return response;
}

module.exports.createReminder = createReminder;

Here is my working code as it stands. This will make a valid 200 when being used with a valid call.

I need to have the 400 response / validation message be returned in teh response object to be handled in the function that calls this function.


Solution

  • In effect, you want to intercept the response and transform it as you wish. There's a section in the axios docs dedicated to interceptors. As an example of what you can do with it, here is what I've used in a recent project with a Laravel back-end:

    axios.interceptors.response.use(
      res => Promise.resolve(res.data),
      error => {
        let message = null;
        if (error.response) {
          // if error has a data.error property, it's an error formatted by server
          if (error.response.data.error) message = error.response.data.error;
          else if (error.response.status === 500) message = 'Oops! Something went wrong.';
        } else {
          // if error has a code property, it's an error defined by axios
          if (error.code === 'ECONNABORTED') message = 'Timeout exceeded';
          else message = 'Oops! Something went wrong.';
        }
        // eslint-disable-next-line prefer-promise-reject-errors
        return Promise.reject({ error: message });
      }
    );
    

    The code above allows me to make axios calls as follows, and always expect the same format:

    axios.post('/url', { data: { ... }})
      .then(({ jsonProp1 }) => console.log(jsonProp1))
      .catch(({ error }) => console.log(error);
    

    Note: if you do create a new axios instance, you need to reinject the response interceptor for this instance too.