Search code examples
javascriptjestjsaxiosspyon

How to mock jest.spyOn for a specific axios call


How do I mock a specific axios call? Imagine 2 GET calls:

await axios.get('api/numbers');
await axios.get('api/letters');

Then this is going on in the test:

const mockGet = jest.spyOn(axios, 'get');
mockGet.mockReturnValueOnce(Promise.resolve({ data: 1 }));
mockGet.mockReturnValueOnce(Promise.resolve({ data: 'a' }));

How do I create a condition for mockReturnValueOnce based on the url passed to axios (say for 'api/numbers' -> return Promise.resolve({ data: 1 }))


Solution

  • So far, there is no method of jestjs to do this. Here is the proposal: Parameterised mock return values

    Here are the solutions:

    1. Use sinon.js

    sinon.js support mock the returned value based on the arguments, there is a method named stub.withArgs(arg1[, arg2, ...]);

    1. Use jest-when - A when(fn).calledWith(args).thenReturn(value) lib for jest

    2. If you insist on using jestjs, since mockReturnValueOnce returns values sequentially(first call, second call, etc.). You can use the below way:

    index.js:

    import axios from 'axios';
    
    export async function main() {
      const numbersRes = await axios.get('api/numbers');
      const lettersRes = await axios.get('api/letters');
      return { numbersRes, lettersRes };
    }
    

    index.test.js:

    import { main } from '.';
    import axios from 'axios';
    
    describe('59751925', () => {
      it('should pass', async () => {
        const mockGet = jest.spyOn(axios, 'get');
        mockGet.mockImplementation((url) => {
          switch (url) {
            case 'api/numbers':
              return Promise.resolve({ data: 1 });
            case 'api/letters':
              return Promise.resolve({ data: 'a' });
          }
        });
        const actual = await main();
        expect(actual.numbersRes).toEqual({ data: 1 });
        expect(actual.lettersRes).toEqual({ data: 'a' });
      });
    });
    

    Unit test results:

     PASS  src/stackoverflow/59751925/index.test.js (11.168s)
      59751925
        ✓ should pass (9ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        13.098s