1
votes

I can't mock axios when it is uses the config convention axios(passAConfigObj). I have no problem mocking when it is axios.get or axios.post. Not trying to introduce a library, because I feel like this can be done.

I have tried mocking the request method that is going to be used axios.post. I tried mocking axios and giving it a return value but wants an AxiosPromise<any>.

const mockedAxios = mocked(axios)

mockedAxios.mockImplementationOnce(() => Promise.resolve(2))

error: TS2322: Type 'Promise<number>' is not assignable to type AxiosPromise<any>

// auth.spec.ts
import { getAuthToken } from '../auth'

import axios from 'axios'
import { mocked } from 'ts-jest/utils'

jest.mock('axios')

describe('getAuthToken', () => {
  const mockedAxiosPost = mocked(axios)

  it('should return ', () => {
    mockedAxiosPost.mockImplementationOnce(() =>
      Promise.resolve({ data: 'response.data' })
    )

    const authToken = getAuthToken()

    expect(authToken).toEqual()
    expect(mockedAxiosPost).toHaveBeenCalledTimes(1)
    expect(mockedAxiosPost).toHaveBeenCalledWith()

  })
})
// auth.ts
import axios from 'axios'

export const getAuthToken = () => {

  const options = {
    url: `url`,
    method: 'POST',
    headers: {
      Authorization: ''
      'Content-Type': '',
    },
    data: {},
  }

  return axios(options)
    .then(response => {
      return response
    })
    .catch(error => {
      console.log(error.response)
    })
}

I expect axios that gets passed a config to internally call axios.post thus working/passing my test.

I have other implementations of axios.post and axios.get that works with this testing style, so that is not the problem. Obviously I can just change my code to use axios.post, but at this point, I am curious more than anything. Thanks in advance :)

1

1 Answers

0
votes

This has been here for a year, and I stumbled onto this thread while trying to solve the same problem.

I was scratching my head for a while, but eventually I managed to crack it.

A bit of context to better understand how I solved it:

I mocked axios for usage with jest, and in a project using Typescript.

That said, this is what I ended up doing:

__mocks__/axios.ts:

import { AxiosResponse } from 'axios';

const axiosResponse: AxiosResponse = {
  data: { falseProp: 'value' },
  status: 200,
  statusText: 'OK',
  config: {},
  headers: {},
};

export default {
  create: jest.fn((config) => {
     const wrapFunction = (param: any) => {
      return Promise.resolve(axiosResponse)
     }

     return wrapFunction
  })
};

This an example of the way I was using axios in the code I was trying to test:

src/MyRequestClass.ts:

import axios, { AxiosInstance, AxiosError } from 'axios'

const axiosInstance = axios.create({
  baseURL: 'https://fake-api-url',
  headers: {
      common: {
          Authorization: authToken
      }
  }
})

const request = {
  method: 'GET',
  url: 'https://fake-api-url/endpoint',
  params: {},
  data: {},
  headers: {}
}

const response = await axiosInstance(request)

Essentially, what I did was make it so the create method returns a function that receives the config object you mentioned (in my case the request object) and always resolves the Promise.

Of course, you can also make it so the Promise fails depending on your test cases.

Hope this helps anyone else!