2

When testing the frontend of my Vue application, I sometimes want to skip the communication with the API backend.

I came up with the following idea:

  • add state in Vuex store: skipServerCommunication.
  • when skipServerCommunication = false: send the axios request as expected
  • when skipServerCommunication = true: return mocked data

The easy way would be to add an check before every call of axios.post(...) or axios.get(...), but I don't want to have to add code in every api function I wrote. So I thought about using the interceptors of axios, but I think it's not possible to stop a request, and just return mocked data, right?

I then thought about wrapping axios, and dynamically returning the real axios instance or a mocked one, which also implements the .post(), .get() and all the other axios functions based on the Store state. I thought about something like this (I'm working with TypeScript):

import store from '@/vuex-store'

const axios = Axios.create( // real store config );
const axiosMock = {
  get(path: string) {
    if (path == '/test') {
      return Promise.resolve( // mocked data );
    }

    return Promise.resolve(true)
  }
}

class AxiosWrapper {
  get instance() {
    if (store.state.skipServerCommunication) {
      return axiosMock;
    }

    return axios
  }
}

export default new AxiosWrapper();

But this solution has some problems:

  1. I need to replace all axios calls with axiosWrapper.instance.get(...). Can I somehow avoid this and mock axios in a way that I can still work with axios.get(...)?
  2. VSCode isn't able to provide autocompletion anymore because the returned instance is either of type AxiosStatic or "MyMockType". So I thought about implementing the AxiosStatic interface, but I struggle to do that correctly because of the two anonymous functions in the AxiosInstance interface. Is there an alternative way to overcome this problem?

1 Answer 1

3

Use axios-mock-adapter instead. You can mock axios calls as needed per test, using advanced matching patterns.

Example usage:

import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'

describe('UserList', () => {
  it('gets users on mount', async () => {
    const mock = new MockAdapter(axios)
    mock.onGet('/users').reply(200, {
      users: [{ id: 1, name: 'John Smith' }],
    })

    const wrapper = shallowMount(UserList)
    await wrapper.find('.getUsersBtn').trigger('click')
    expect(wrapper.vm.users[0].id).toBe(1)
  })
})
Sign up to request clarification or add additional context in comments.

4 Comments

That's the thing: I'm not in any test environment but in production! I want my application to mock the data when a certain condition is met during the "real" execution. In other words: I want to be in charge whether an axios call is really made or just some mocked data is returned.
And you could still do that with axios-mock-adapter. It can be used outside a test environment, although I find it odd to be testing in production.
I'm not testing anything. In certain circumstances (while in "demo" mode) I explicitly want to just return mocked data instead of calling the real API.
So is it possible to just mock axios on the fly based on a state from Vuex?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.