Jessica
Jessica

Reputation: 43

Jest - Mock Inner axios API Call

I saw a similar question asked here, but I don't know if I'm just not understanding or if this is a different case? I have a hook that exposes a function called fetchPeople which calls a function search that is ultimately the api call I'm making. I've followed the examples on jest about mocking axios, but it seems like my test is still (maybe) making the physical api call and not returning my resolved mock values. Through debugging I've realized the response is this:

baseURL: "mock.api.imirwin.com"
headers: {}
responseType: "json"
__proto__: Object

This is the structure of my code:

services/people.js

async function search(params) {
 const response = await axios.get(url)

 return {
  data: response.data,
  links: response.links,
  count: response.count,
 }
}

useSearchPeople.js

import { searchPeople } from 'services/people'

const fetchPeople = async term => {
 const { data } = await searchPeople({ term })

 return formatPeople(data)
}

useSearchPeople.test.js

import useSearchPeople from './useSearchPeople'
import axios from 'axios'

const { fetchPeople } = useSearchPeople()

jest.mock('axios')

describe('useSearchPeople', () => {
 it('returns an array of people', async () => {
  axios.get.mockResolvedValue(response)
  const data = await fetchPeople('term')
 )}
}

The error I get back from this is:

    TypeError: Cannot read property 'total' of undefined

      138 |     data: deserializerAndCase().deserialize(response),
      139 |     links: response.links,
    > 140 |     count: response.meta.total,
          |                          ^
      141 |   }
      142 | }

Which I understand means that the api is being called, but the mocked response is not returned.

From fiddling around, I noticed that if I mock my services jest.mock('services/people'), it doesn't make the physical call, but the mocked response is still not returned, and I instead get this error

    TypeError: Cannot destructure property `data` of 'undefined' or 'null'.
      32 | const fetchPeople = async term => {
    > 33 |   const { data } = await searchPeople({ term })
         |         ^
      34 |   return formatPeople(data)
      35 | }
      36 | 

Any insight would be greatly appreciated. Edit: I should add, that what I'm ultimately trying to test, is that formatPeople function

Upvotes: 2

Views: 1823

Answers (1)

Jessica
Jessica

Reputation: 43

Apologies if my original question was not up to standard. I tried my best to truncate the most relevant information but realized I might have omitted more than I should have. Good news is that I ended up solving my problem. Here is what worked for me, should anyone run into the same situation:

In my useSearchPeople.test.js, I found I could mock the actual import of my api function that was used in my fetchPeople function in the useSearchPeople.js hook. What I did was this:

useSearchPeople.test.js

import { useSearchPeople } from './useSearchPeople'
import { searchPeople } from 'services/people'

const response = { data: [{}] }
const { fetchPeople } = useSearchPeople()

jest.mock('services/people', () => {
 return {
   search: jest.fn().mockReturnValue(response)
 }
})

describe('useSearchPeople hook', () => {
 it('returns data from external api call', async () => {
  const data = await fetchPeople('something')

  expect(data.length).toBe(1)
 }
})

Upvotes: 2

Related Questions