Mateusz Urbański
Mateusz Urbański

Reputation: 7862

Testing Vuex action that calls external api

In my Vue.js project I have the following Vuex action:

import { HTTP } from '@/services/http'

export const actions = {
  loginUser ({ commit }, params) {
    HTTP.post(
      'v1/login',
      { email: params.email, password: params.password }
    ).then(response => {
      localStorage.setItem('access_token', response.data.token)
      commit('SET_USER', response.data)
    }).catch(error => {
      commit('SET_LOGIN_ERROR', error.response.data.error)
    })
  }
}

I'm using Mocha + Karma for unit tests. How can I test that action?

Upvotes: 0

Views: 320

Answers (1)

Brett
Brett

Reputation: 4269

It's important that you mock/stub any dependencies. Your first challenge is mocking the HTTP service because, as written, your tests won't pass unless you have an Internet connection to the backend server. Look into dependency injection to solve this.

To test actions, I borrowed the idea from Vuex's suggestion. Create a stub of the commit function that accepts the type and payload of each mutation the action calls and then compare that to what is expected. If the list of expected mutations match the list of mutations the commit stub calls when the action is executed, then the action passes the test.

This is a trivial example that I wouldn't use in production, but it helps to illustrate the idea:

let count = 0
let errors = []
let mutations = [
  { type: 'SET_USER', payload: 'whatever response.data is expected to be' }
]

function commit(type, payload) {
  const mutation = mutations[count]

  try {
    expect(mutation.type).to.equal(type)
    if (payload) { expect(mutation.payload).to.deep.equal(payload) }
  } catch (error) {
    errors.push(error)
  }

  count++
}

actions.loginUser({ commit }, { email: '[email protected]', password: '12345' })

Upvotes: 1

Related Questions