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

No request to respond to! when used along with multiple async await #46

Open
AnandShiva opened this issue Feb 25, 2020 · 10 comments
Open

Comments

@AnandShiva
Copy link

Thanks for your package. Love it !
But I seem to have an issue with it when using it along with async-await functions.
Test Code looks like
test("authenticate", async () => { let promiseObj = authenticate(email, password).then((msg) => {}).catch(catchFn) // simulating a server response let responseObj = { data: ["centralpet"] }; mockAxios.mockResponse(responseObj); expect(catchFn).not.toHaveBeenCalled(); return promiseObj; })

Now my source code - authenticate implementation looks like

authenticate = async (email, password) => { //This called a chrome async method. Not axios. let client = await utils.updateClientDetailsFromEmail(email); // This calls the axios methods. let status = await httpService.makeNetworkCall(requestObject); return status; }

Since inside the authenticate I am using await, the function gets paused before calling axios.
Meanwhile, the calling function continues execution and goes to mockResponse.
There mockAxios finds that no axios functions are in Queue so it throws No request to respond to! error.
If I await the authenticate call the mockResponse never gets executed so axios times out.

Can you check this issue or is there any workaround or config I am missing to avoid queuing of axios calls?

@kingjan1999
Copy link
Collaborator

This looks like a duplicate of #44. Currently, I am not aware of any workaround for this, except for splitting up the two await calls in two different functions. But I will look at this again soon

@AnandShiva
Copy link
Author

@kingjan1999 Any reason why mockResponse should be set after the axios call has been made?
If it is possible to change this architecture I can fork a branch and have this mocking response after the call to be a configuration parameter.

@kingjan1999
Copy link
Collaborator

This is currently due to how this library works: It takes any requests made, puts them into a queue and then pops the first one (or the specified one) when mockResponse is called. Feel free to make a pull request to make this more flexible

@Martin7mind
Copy link

@AnandShiva did you find a workaround?

@BrendanBall
Copy link

Why can't this work like a regular jest mock where you're able to for example do

  test('foo', async () => {
    const mock = jest.fn()
    mock
      .mockResolvedValueOnce({ foo: 'bar' })
      .mockResolvedValueOnce({ foo: 'bar' })
      .mockRejectedValueOnce(new Error('oh no'))
    await expect(mock()).resolves.toEqual({ foo: 'bar' })
    await expect(mock()).resolves.toEqual({ foo: 'bar' })
    await expect(mock()).rejects.toThrowError(new Error('oh no'))
  })

Jest fully supports async tests and seen as this package is specifically written for jest I don't see a reason to work outside of its framework.

@pedrotorchio
Copy link

Why can't this work like a regular jest mock where you're able to for example do

  test('foo', async () => {
    const mock = jest.fn()
    mock
      .mockResolvedValueOnce({ foo: 'bar' })
      .mockResolvedValueOnce({ foo: 'bar' })
      .mockRejectedValueOnce(new Error('oh no'))
    await expect(mock()).resolves.toEqual({ foo: 'bar' })
    await expect(mock()).resolves.toEqual({ foo: 'bar' })
    await expect(mock()).rejects.toThrowError(new Error('oh no'))
  })

Jest fully supports async tests and seen as this package is specifically written for jest I don't see a reason to work outside of its framework.

this' been a pain for me too

@aarlaud
Copy link

aarlaud commented Jul 16, 2020

I get the same "No request to respond to!" after 10 successful responses using await. My first 10 test cases (with one await call in each) pass well and then this fails. Tried to change the code but always seems to be a 10 limit somehow. Not clear what seems to cause this as I could not see something like a limit in the queue size. Any ideas? Nevermind me 🤦

@gnarea
Copy link

gnarea commented Aug 27, 2020

In case it helps anyone else running into this and/or #44: Try axios-mock-adapter

@ghill-legwork
Copy link

ghill-legwork commented May 27, 2021

I worked around this by doing something like:

    it('can pass through all filter params to the API', async (): Promise<void> => {
      mockAxios.get.mockImplementationOnce(() => {
        return Promise.resolve(resultArray);
      });
      const result = await getResource(
        {}, // query string params
      );
      const requestConfig = mockAxios.get.mock.calls[0][1]; // First call, second arg
      const requestUrl = mockAxios.get.mock.calls[0][0]; // First call, second arg
      expect(requestUrl).toEqual('/example/resource/endpoint');
      expect(requestConfig.params).toEqual({});
      expect(result).toEqual(resultArray);
    });

Excuse the pulling out of the mock call args, I had to only test a subset of them but you get the general idea.

@douglascayers
Copy link

Came here with the same struggle.

My solution was to mock both axios and got using jest's out-of-the-box mocking framework. To clarify, you don't have to use both http packages, I'm just showing that the same mocking concept can be applied to either you're using.

For this example, I'm using the following versions:

  • "axios": "^0.21.1"
  • "got": "^11.8.3"
  • "jest": "^28.1.3"
  • "ts-jest": "^28.0.7"
  • "typescript": "^4.9.5"
import axios, { AxiosStatic } from 'axios';
import got, { Got } from 'got';

jest.mock('axios');
jest.mock('got');

describe('mock-test', () => {
  let mockedAxios: jest.MaybeMocked<AxiosStatic>;
  let mockedGot: jest.MaybeMocked<Got>;

  beforeEach(() => {
    mockedAxios = jest.mocked(axios);
    mockedGot = jest.mocked(got);
  });

  afterEach(() => {
    jest.resetAllMocks();
  });

  test('mocked post', async () => {
    const mockResponse = {
      ok: true,
      result: {
        id: 42,
        name: 'Doug'
      },
    };

    mockedAxios.post = jest.fn().mockReturnValue(mockResponse);

    const response = await client.createUser({ name: 'Doug' });

    expect(mockedAxios.post).toHaveBeenCalledWith(
      expect.stringContaining('/user'),
      {
        name: 'Doug'
      }
    );

    expect(response).toBe(mockResponse.result);
  });

  test('mocked error', async () => {
    mockedGot.get = jest.fn().mockRejectedValue(new Error('failure'));

    await expect(async () => {
      await client.getUserById(42);
    }).rejects.toThrow('failure');

    expect(mockedGot.get).toHaveBeenCalledWith(
      expect.stringContaining('/user/42'),
    );
  });
});

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

No branches or pull requests

9 participants