wa-rren-dev
wa-rren-dev

Reputation: 327

Jest - spy on nested promise (axios)

I'm trying to spy on the arguments that have been passed to an async function with Jest.

My very simple module...

// data_loader.js
import axios from "axios";

export const data_loader = ( options ) => {
    return axios( generateUrl( options ) )
        .then( response => response.data );
};

and my test...

// data_loader.test.js
import * as data_loader from "./data_loader";

// this spies on the "load" function and passes
it("should be called once", () => { 
    const spy = data_loader.load = jest.fn();
    data_loader.load(options);
    expect(spy).toHaveBeenCalledTimes(1);
});

// here's where i'm trying to spy on axios to see if it is called with appropriate arguments 
it("axios should be called with the supplied options", () => {
    // have tried all syntax under the sun
});

If I understand correctly I believe that I need to mock axios as there's no reason it ever needs to be really called to check the arguments that it received.

I've tried jest.mock("axios"), jest.spyOn("axios") and a couple of mocking libs for Axios but I can't get my head around the syntax.

Upvotes: 2

Views: 2597

Answers (1)

wa-rren-dev
wa-rren-dev

Reputation: 327

So after a lot of trying I should have learned to RTFM.

I used axios-mock-adapter to mock the call before the data_loader.load function was called. I also amended the load function to return a promise.

You can then assert on the result of the promise by returning your call. That seems to be how Jest knows to wait.

the module...

// data_loader.js
import axios from "axios";

export const load = (options) => {
    return new Promise((resolve, reject) => {
        axios(generateUrl(options))
            .then(response => {
                resolve(response);
            })
            .catch(err => {
                reject(err);
            });
    });
};

and the test...

// data_loader.test.js
import axios from "axios"; // we need to import this so the mocking library can wrap it
import MockAdapter from "axios-mock-adapter";

const mock = new MockAdapter(axios); // wrap the real axios with the fake axios

it("axios should be called with the generated url", () => {
    expect.assertions(1); // tell Jest that we're expecting one assertion
    mock.onAny().reply(200, {}); // use the mock on any call to axios
    return loader.load(...options).then(response => { // "return" is vital here - jest won't wait without it
        expect(response.config.url)
            .toBe("/my-generated-url");
    });
});

Upvotes: 2

Related Questions