Home > other >  Why is the response from my api not being returned to my unit test?
Why is the response from my api not being returned to my unit test?

Time:03-15

I strongly suspect this is to do with the api using an asynchronous call, but so far as I can see, I have 'awaits' in all the right places.

The unit test making the call:

const { expect } = require('@jest/globals');
const { getWorkerId } = require('../api');

describe("Workers api", () => {
    test("it should return a status of 200", async () => {
        let response = await getWorkerId(21882000)
        expect(response.status).to.equal('200')
    });
});

and the api itself:

const axios = require('axios');

const getWorkerId = async (id) => {
    await axios.get(`http://localhost:8080/v1/workers/${id}`)
        .then(function (response) {
            console.log(response.status);
            return response;
        })
        .catch(function (error) {
            console.log('Error number: ', error.errno);
            console.log('Error code: ', error.code);
            return error;
        })
};

module.exports = { getWorkerId };

The line 'console.log(response.status)' outputs '200' as expected and if I change the code to display 'response', sure enough there it is. Yet, my unit test's expect call comes back with: 'TypeError: Cannot read property 'equal' of undefined'.x

CodePudding user response:

It is quite common to get confused with async/await and Promises in JS. I will try to be concise here, but it is a large topic, with a lot of details, so bear with me on this one!

First and foremost, when using async/await, there is no need to use .then(). The await keyword will (quite literally) await for the Promise to be resolved, and get its returned value. Similarly, the .then() will get the resolved value of the promise, which is the parameter you receive, in your case, it is the response inside the .then().

So, the await, and the .then() work in similar ways, and you can even use them together, like this:

const response = await axios.get('https://jsonplaceholder.typicode.com/todos/1').then((data) => {
  console.log(data)
  return data
}).catch((err) => {
  console.log(err)
  return err
})

console.log(response.status) // Output is 200

What is happening above, is that the await gets the return of .then(), and assigns it to response. So, if you use async/await together with .then(), you should have a variable to receive the value returned by the .then(), so that you can use it outside of the scope.

However, in your case, we have the following:

const getJsonPlaceholder = async (id) => {
  await axios.get(`https://jsonplaceholder.typicode.com/todos/${id}`).then((data) => {
    console.log(data)
    return data
  }).catch((err) => {
    console.log(err)
    return err
  })
}

const response2 = await getJsonPlaceholder()

console.log(response2.status)// Output is "Cannot read property 'status' of undefined"

What is happening is that the await receives the returned value by .then(), assigns it to nothing at all, and the function getJsonPlaceholder returns undefined, which is the default in JS for functions that do not return anything.

Here you can find a great summary of async/await .then() and .catch() usecases in JS.

And, finally, for your test case to pass, drop the .then(), assign the returned value of the axios request to a variable, and return this variable on the function getWorkerId, this should be enough!

  • Related