Skip to content

Un poco más sobre Vuex ​

Las partes principales que queremos probar unitariamente en Vuex son mutaciones y acciones.

Prueba de Mutaciones ​

Las mutaciones son muy sencillas de probar, porque son solo funciones que dependen completamente de sus argumentos. Un truco es que si está utilizando módulos ES2015 y coloca sus mutaciones dentro de su archivo store.js, además de la exportación predeterminada, también debe exportar las mutaciones como una exportación con nombre:

js
const state = { ... }

// export `mutations` as a named export
export const mutations = { ... }

export default createStore({
  state,
  mutations
})

Ejemplo probando una mutación usando Vitest (puede usar cualquier biblioteca de framework/assertion que desee):

js
// mutations.js
export const mutations = {
  increment: state => state.count++
}
js
// mutations.spec.js
import { mutations } from '@/store/mutations'

// destructure assign `mutations`
const { increment } = mutations

describe('mutations', () => {
  it('INCREMENT', () => {
    // mock state
    const state = { count: 0 }
    // apply mutation
    increment(state)
    // assert result
    expect(state.count).toEqual(1)
  })
})

Prueba de Acciones ​

Las acciones pueden ser un poco más complicadas porque pueden llamar a API externas. Cuando probamos acciones, generalmente necesitamos hacer algún nivel de simulación; por ejemplo, podemos abstraer las llamadas a la API en un servicio y simular ese servicio dentro de nuestras pruebas. Para simular fácilmente las dependencias, podemos usar algún módulo mock para agrupar nuestros archivos de prueba.

Ejemplo probando una acción asíncrona:

js
export const actions = {    
  incrementAsync({ commit, state }) {
    return new Promise((resolve) => {
      setTimeout(() => {
        commit('increment', state)
        resolve()
      }, 1000)
    })
  }
}
js
// actions.spec.js
import { actions } from "@/store/actions"

const testAction = (action, payload, state, expectedMutations, done) => {
  let count = 0

  // mock commit
  const commit = (type, payload) => {
    const mutation = expectedMutations[count]

    try {
      expect(type).toEqual(mutation.type)      
    } catch (error) {
      done(error)
    }

    count++
    if (count >= expectedMutations.length) {
      done()
    }
  }

  // call the action with mocked store and arguments
  action({ commit, state }, payload)

  // check if no mutations should have been dispatched
  if (expectedMutations.length === 0) {
    expect(count).toEqual(0)
    done()
  }
}

describe('actions', () => {
  it('incrementAsync', done => {
    testAction(actions.incrementAsync, null, {}, [{type: 'increment'}], done)
  })
})

Con los espías disponibles en su entorno de prueba, puede usarlos en lugar del ayudante testAction:

js
// actions.spec.js
import { actions } from "@/store/actions"

describe('actions', () => {
  it('incrementAsync', () => {  
    const commit = vi.spyOn(actions, 'incrementAsync')    
    const state = {}

    actions.incrementAsync({ commit, state})

    expect(commit).toHaveBeenCalledTimes(1)
  })
})

Pruebas de Captadores ​

Si sus getters tienen cálculos complicados, vale la pena probarlos. Los getters también son muy sencillos de probar por la misma razón que los mutations.

Ejemplo probando un getters:

js
// getters.js
export const getters = {
  filteredProducts (state, { filterCategory }) {
    return state.products.filter(product => {
      return product.category === filterCategory
    })
  }
}
js
// getters.spec.js
import { getters } from '@/store/getters'

describe('getters', () => {
  it('filteredProducts', () => {
    // mock state
    const state = {
      products: [
        { id: 1, title: 'Apple', category: 'fruit' },
        { id: 2, title: 'Orange', category: 'fruit' },
        { id: 3, title: 'Carrot', category: 'vegetable' }
      ]
    }
    // mock getter
    const filterCategory = 'fruit'

    // get the result from the getter
    const result = getters.filteredProducts(state, { filterCategory })

    // assert the result
    expect(result).to.deep.equal([
      { id: 1, title: 'Apple', category: 'fruit' },
      { id: 2, title: 'Orange', category: 'fruit' }
    ])
  })
})

Ejecución de Pruebas ​

Si sus mutaciones y acciones están escritas correctamente, las pruebas no deberían depender directamente de las API del navegador después de una simulación adecuada.