Mocking axios in Jest returns axios is not defined

Viewed 743

I have seen similar questions but they dont actually address what am looking for.

so am using using axios globally in app.js for my vue app like window.axios=require('axios')

then in auth.js i have this

export function login(credentials){
    return new Promise((res,rej) => {
        axios.post('/api/auth/login', credentials)
            .then((response) => {
                res(response.data);
            })
            .catch((err) => {
                rej("Wrong email or password");
            })
    });
}

which works fine on the login page

however in my test script

jest.mock("axios", () => ({
    post: jest.fn(() => Promise.resolve({data:{first_name:'James','last_name':'Nwachukwu','token':'abc123'}}))
}));


    import axios from 'axios'
    import {login} from '../helpers/auth'
    it("it logs in when data is passed", async () => {
        const email='super@gmail.com'
        const password='secret';
        const result=await login({email,password});
        expect(axios.post).toBeCalledWith('/api/auth/login',{"email": "super@gmail.com", "password": "secret"})
        expect(result).toEqual({first_name:'James','last_name':'Nwachukwu','token':'abc123'})
    })

shows axios is not defined

but if i change auth.js to

import axios from 'axios'
export function login(credentials){
    return new Promise((res,rej) => {
        axios.post('/api/auth/login', credentials)
            .then((response) => {
                res(response.data);
            })
            .catch((err) => {
                rej("Wrong email or password");
            })
    });
}

test passes. how do i run the test without having to import axios on each vue file

2 Answers

I had the same problem just now. I am also including axios via window.axios = require('axios'); in my app.js.

The solution is to set your axios mock on window.axios in your test. So instead of this (incorrect):

axios = {
    post: jest.fn().mockName('axiosPost')
}

const wrapper = mount(Component, {
    mocks: {
        axios: axios
    }
})

When your component code calls axios.whatever it is really calling window.axios.whatever (as I understand it), so you need to mirror that in your test environment:

window.axios = {
    post: jest.fn().mockName('axiosPost')
}

const wrapper = mount(Component, {
    mocks: {
        axios: window.axios
    }
})

And in your test:

expect(window.axios.post).toHaveBeenCalled()

The above method works fine until you want to chain then to it. In which case you need to set your mock up like this:

window.axios = {
    get: jest.fn(() => {
        return {
            then: jest.fn(() => 'your faked response')
        }
    }),
}

You don't need to pass it into the component mock though, you can just mount (or shallowMount) the component as usual

Related