Vue.jsとVuexとユニットテスト

どこもかしこも混雑していることがわかっているので、連休前半は家からほとんど出ることがありませんでした。

早速本題。

component内のボタンがクリックされたらstateが変更される、けどstateが変更されるだけで描画には影響がない、といった場合にはテストをどう書けばいいのでしょうか。いろいろと試したところ、なんとなくまとまってきたので整理してみます。

ここでテストする必要があるものは、簡単に分けてみると以下の2つになるのではないかと思います。

  • ボタンをクリックするとmethod(もしくはaction)が呼ばれる
  • stateが変更される

まずは後者ですが、Vuexにおいてstateを変更するにはmutationをcommitするしかないので、mutationのテストとしてしまえばいいはず。さっそく書いてみます。mochaをフレームワークに、アサーションにはchaiを使っています。

import { mutations } from 'mutations'
import * as types from 'mutation-types'

describe('test for mutations', () => {
  it('do CHANGE_STATE', () => {
    const state = {
      hogepiyo: {}
    }

    const hogepiyoData = {
      hoge: 'hogehoge',
      piyo: 'piyopiyo'
    }

    mutations[types.CHANGE_STATE](state, hogepiyoData)

    assert.strictEqual(state.hogepiyo, hogepiyoData)
  })
})

残ったほうについては、componentをマウントしてクリックイベントを発火させればテストできそう。method内の処理は見る必要がないので、sinonを使ってスタブにしておきます。

import Vuex from 'vuex'
import { shallow, createLocalVue } from '@vue/test-utils'

import { state } from 'state'
import App from 'App.vue'

const localVue = createLocalVue()
localVue.use(Vuex)

describe('test for App.vue', () => {
  let store

  beforeEach(() => {
    store = new Vuex.Store({
      state
    })
  })

  it('call submit', () => {
    const wrapper = shallow(App, { store, localVue })
    const clickMethodStub = sinon.stub()

    wrapper.setMethods({ submit: clickMethodStub })
    wrapper.find('.btn-submit').trigger('click')

    assert.strictEqual(clickMethodStub.called, true)
  })
})

こんなものでしょうか。今回の場合、mutationのテストはさて置き、componentのテストは不要な気もします。どこまでテストするのか、は個々人の好みによるところもあるのでなんとも言えませんが。