axios-mock-adapter icon indicating copy to clipboard operation
axios-mock-adapter copied to clipboard

Possible to register multiple MockAdapters?

Open rally25rs opened this issue 6 years ago • 8 comments

I have a few libraries split out as sort of a monorepo. Each library has it's own mocks that I want to register, so each does a const mockApi = new MockAdapter(axios); however it seems that new MockAdapter() replaces all previous MockAdapters, so only the last library included has it's mocks registered.

Since my libraries are split out to different packages, there isn't an easy way to pass around a single MockAdapter.

Is there a way to handle this? Thanks for any help!

rally25rs avatar Jun 19 '19 15:06 rally25rs

+1

Would definitely like this as a feature.

gburning avatar Oct 10 '19 13:10 gburning

I've come across this problem too, but not directly in a testing situation, more that I'm building the front-end of an app that doesn't have a back-end yet, so I want to make something that works with the backend responses "faked". The way that I achieved this is as follows:

import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';

function mockAuthGet() {
  const mock = new MockAdapter(axios, { delayResponse: 1000 });
  mock.onGet('/api/auth').reply(({ headers }) => {
    // ...
  });
  return () => mock.restore();
}
export const fetchAuth = (token = null) => async (dispatch) => {
  const restore = mockAuthGet();
  const user = await axios.get('/api/auth');
  await dispatch({ type: 'FETCH_AUTH_FULFILLED', user });
  restore();
};

In tests you can get a similar but cleaner version by using the testing library's before/after beforeEach/afterEach or various equivalents.

I do still think there should be a non-singleton instance available though. Perhaps just something like:

const mock = new MockAdapter.once(axios, { delayResponse: 1000 });
// or
const mock = new MockAdapter(axios, { delayResponse: 1000, mutate: false });
// (it's a Monday morning and my naming-things-brain isn't working yet)

It's also annoying having it as a singleton because I'd quite like to have a different delayResponse per request, but this is globally defined.

MaffooBristol avatar Jan 13 '20 09:01 MaffooBristol

This is also an issue when running tests in parallel. If a test is using a different MockAdapter, it will be used for all other tests while it's being set. The reference is shared, causing other tests to use the wrong MockAdapter.

Anyone found a way to prevent this so far?

GabLeRoux avatar Feb 04 '20 16:02 GabLeRoux

any fix to this?

jesalazaro avatar Jan 11 '23 20:01 jesalazaro

I think the issue is that it attaches to the axios instance, and if you use axios as a singleton, then running in parallel will cause inconsistency.

I ended up introducing a lightweight dependency injection so that a separate/isolated axios instance with attached mock adapter is used by the application in testing env.

before(() => {
  http = axios.create()
  httpMock = new MockAdapter(http)
}) 

afterEach(() => {
  httpMock.reset()
})

it ('test something', () => {
  // inject http into the app/component
  // mock responses
  // test  
})

Mihailoff avatar Sep 24 '23 04:09 Mihailoff

@GabLeRoux is that true ?

My test are parallel and they work fine. Could you post a repo to reproduce it

Amerr avatar Nov 02 '23 08:11 Amerr

Hey there, it's been almost 4 years now. I don't have anything to reproduce somehwere, but that shouldn't be too hard to create a blank project and reproduce this.

Not sure if this is still an issue tho.

GabLeRoux avatar Nov 05 '23 14:11 GabLeRoux

Still an issue.

AaronTrazona avatar Mar 05 '24 03:03 AaronTrazona