knee-cola / jest-mock-axios

Axios mock for Jest
252 stars 42 forks source link

Mocking nested axios requests #41

Closed kevr closed 4 years ago

kevr commented 5 years ago
axios.request({
  url: "a",
  method: "post",
  data: "abc"
}).then((response) => {
  if(response.status === 200) {
    axios.request({
      url: "b",
      method: "get"
    }).then((response) => {
      if(response.status === 200)
        // Do something with response.data
    });
  }
});

const firstRequest = mockAxios.getReqByUrl("a"); // Returns correct request
const secondRequest = mockAxios.getReqByUrl("b"); // Returns correct request
expect(mockAxios.request).toBeCalledTimes(2); // Succeeds
mockAxios.mockResponse({ data: "" }, firstRequest);
mockAxios.mockResponse({ data: "" }, secondRequest);

With this code being used in a test, I can't get the nested axios.request to be completed before the test is complete. I've tried using a fake jest timer to allow the test extra time in case I was just ending the test before the promises were resolved, but it didn't help anything.

Could anyone show an example of mocking nested requests with jest-mock-axios?

To clarify: The test is succeeding, however the nested axios request in the code being tested is not being covered by jest. The second nested request seems to call axios.request properly, but .then((response) => ...); is never run.

Thanks!

kingjan1999 commented 5 years ago

The following code works for me:

    it('works for nested function', (done) => {
        const callback = jest.fn();
        axios.request({
            url: "a",
            method: "post",
            data: "abc"
        }).then((response) => {
            if (response.status === 200) {
                axios.request({
                    url: "b",
                    method: "get"
                }).then((response) => {
                    callback()
              });
            }
        });

        const firstRequest = mockAxios.getReqByUrl("a"); // Returns correct request
        expect(mockAxios.request).toBeCalledTimes(1); // Succeeds
        mockAxios.mockResponse({ data: "" }, firstRequest);
        setImmediate(() => {
            const secondRequest = mockAxios.getReqByUrl("b"); // Returns correct request
            expect(mockAxios.request).toBeCalledTimes(2); // Succeeds  
            mockAxios.mockResponse({ data: "" }, secondRequest);  
            expect(callback).toHaveBeenCalled();
            done();
        })
    })

I think you need to use setImmediate here to give the promise a chance to be processed.

Please try and report back!