Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mockAxios.create() may return a new instance of mockAxios #59

Open
spanitz opened this issue Aug 31, 2020 · 8 comments
Open

mockAxios.create() may return a new instance of mockAxios #59

spanitz opened this issue Aug 31, 2020 · 8 comments

Comments

@spanitz
Copy link

spanitz commented Aug 31, 2020

Assuming the following use case:

// api.js
import axios from 'axios';

export function config() {
  v1.defaults.baseURL = `${API_BASEURL}/v1`;
  v2.defaults.baseURL = `${API_BASEURL}/v2`;
  // ...
}

export const v1 = axios.create();
export const v2 = axios.create();
export default v1;

Basic test scenario:

// api.test.js
import mockAxios from 'axios';
import * as Api form './api'

describe('Api', () => {
  test('proper configuration', () => {
    Api.config();

    // the following expectation fails because `mockAxios.create()` returns the singleton
    // whose `defaults.baseURL` was overwritten with `${API_BASEURL}/v2` already
    expect(Api.v1.defaults.baseURL).toEqual(`${API_BASEURL}/v1`);
    expect(Api.v2.defaults.baseURL).toEqual(`${API_BASEURL}/v2`);
  })
})

Because mockAxios works with a shared state, a workaround would be to override the create method and simply return a shalow copy of mockAxios (as in the following example) Since axios.create() actually appears to be a factory, the mock could also return a new instance. I think this would be ideal. What do you guys think?

//__mocks__/axios.js
import mockAxios from 'jest-mock-axios';
import { cloneDeep } from 'lodash';

mockAxios.create = jest.fn(() => cloneDeep(mockAxios));

export default mockAxios;
@kingjan1999
Copy link
Collaborator

Hi,

I agree that there is indeed room for improvement when using multiple axios instances. I'll see how it can be improved over the weekend.

@kingjan1999
Copy link
Collaborator

Hi,

so I implemented the desired behavior in the 59-multiple-instances branch as a proof of concept.

This works, but it adds a significant new problem: If you create separate axios instances via axios.create() you can no longer mock them using the mockAxios default export, because it is two different instances with no shared promise queue. See LowercaseProxy.ts and the corresponding spec as an minimal example for this. Similar to your example above, the axios instances need to be exported by the code under test and imported by the test file.

This is somewhat unsatisfactory and I need to think a little bit more about this and how this can be changed to be more backward-compatible (any input welcome!)

@rcg-dev
Copy link

rcg-dev commented Nov 27, 2020

I am getting this error ( I am assuming it is tied to this new update)

TypeError: axios.create is not a function

I have a singular instance being created in my file.

sd.instance = axios.create({
                baseURL: process.env.SDApiUrl,
                httpsAgent: new https.Agent({ keepAlive: true }),
                headers: { 'Content-Type': 'application/json' }
            })

@kingjan1999
Copy link
Collaborator

@rcg-dev I failed to reproduce this error (which isn't that surprising, as create() is used in the tests for this library as well). Can you do console.log to find out what axios.create is, if not a function?

@httpete
Copy link

httpete commented Mar 3, 2021

I'm hitting the issue with different instances of axios - is that going to get released? Seems that the fix is in.

@kingjan1999
Copy link
Collaborator

@httpete The patch for this is still not merged but only in the branch linked above. As described above I was (and still am) hesitant to merge this in as it would break existing, more simple usages of this library. I'm still unsure how to solve this appropriately. Any input welcome.

@ryanrhee
Copy link

my $0.02:

when using instances of axios, they should be passed in. in other words, a class that calls _axiosInstance.post() should take in the _axiosInstance as a dependency somehow, e.g. in its constructor.

i would expect the jest-mock-axios library to give me the ability to instantiate a mocked AxiosInstance instance that I can then pass into my constructor.

@trajano
Copy link

trajano commented Apr 21, 2022

so I implemented the desired behavior in the 59-multiple-instances branch as a proof of concept.

The link does not appear to work anymore.

In my case I use multiple axios instances each configured with it's own interceptor. This seems to wipe out the axios instance that I create.

In the end I just implemented by own https://stackoverflow.com/a/71961832/242042

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants