|
@@ -0,0 +1,215 @@
|
|
|
|
+# テスト
|
|
|
|
+
|
|
|
|
+私たちが Vuex でユニットテストしたい主な部分はミューテーションとアクションです。
|
|
|
|
+
|
|
|
|
+### ミューテーションのテスト
|
|
|
|
+
|
|
|
|
+ミューテーションは完全に引数に依存しているだけの関数であるため、テストするのがとても簡単です。効果的なやり方として、もし ES2015 のモジュールを使っていて `store.js` ファイルの中にミューテーションがあるなら、デフォルトエクスポートに加えて、名前付きエクスポートでミューテーションをエクスポートできます。
|
|
|
|
+
|
|
|
|
+``` js
|
|
|
|
+const state = { ... }
|
|
|
|
+
|
|
|
|
+// 名前付きエクスポートでミューテーションをエクスポートする
|
|
|
|
+export const mutations = { ... }
|
|
|
|
+
|
|
|
|
+export default new Vuex.Store({
|
|
|
|
+ state,
|
|
|
|
+ mutations
|
|
|
|
+})
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+Mocha + Chai を使用してミューテーションをテストする例です(あなたの好きな任意のフレームワーク/アサーションライブラリを使用できます):
|
|
|
|
+
|
|
|
|
+``` js
|
|
|
|
+// mutations.js
|
|
|
|
+export const mutations = {
|
|
|
|
+ increment: state => state.count++
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+``` js
|
|
|
|
+// mutations.spec.js
|
|
|
|
+import { expect } from 'chai'
|
|
|
|
+import { mutations } from './store'
|
|
|
|
+
|
|
|
|
+// ミューテーションの分割束縛
|
|
|
|
+const { increment } = mutations
|
|
|
|
+
|
|
|
|
+describe('mutations', () => {
|
|
|
|
+ it('INCREMENT', () => {
|
|
|
|
+ // ステートのモック
|
|
|
|
+ const state = { count: 0 }
|
|
|
|
+ // ミューテーションを適用する
|
|
|
|
+ increment(state)
|
|
|
|
+ // 結果を検証する
|
|
|
|
+ expect(state.count).to.equal(1)
|
|
|
|
+ })
|
|
|
|
+})
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### アクションのテスト
|
|
|
|
+
|
|
|
|
+アクションは外部の API を呼び出す可能性があるため、ミューテーションのテストよりも少し注意が必要です。アクションをテストするとき、通常、いくつかの段階でモックを作る必要があります。例えば API 呼び出しをサービスとして抽象化し、そしてテストの内部ではそのサービスをモックにすることができます。簡単に依存関係をモック化するために、Webpack と [inject-loader](https://github.com/plasticine/inject-loader) を使ってテストファイルをバンドルすることができます。
|
|
|
|
+
|
|
|
|
+非同期なアクションのテストの例:
|
|
|
|
+
|
|
|
|
+``` js
|
|
|
|
+// actions.js
|
|
|
|
+import shop from '../api/shop'
|
|
|
|
+
|
|
|
|
+export const getAllProducts = ({ dispatch }) => {
|
|
|
|
+ dispatch('REQUEST_PRODUCTS')
|
|
|
|
+ shop.getProducts(products => {
|
|
|
|
+ dispatch('RECEIVE_PRODUCTS', products)
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+``` js
|
|
|
|
+// actions.spec.js
|
|
|
|
+
|
|
|
|
+// inline loader のために require 構文を使用する
|
|
|
|
+// ここでは inject-loader を使って、モック化された依存関係を注入できるようにするモジュールファクトリーを返す
|
|
|
|
+import { expect } from 'chai'
|
|
|
|
+const actionsInjector = require('inject!./actions')
|
|
|
|
+
|
|
|
|
+// モックによってモジュールを作成する
|
|
|
|
+const actions = actionsInjector({
|
|
|
|
+ '../api/shop': {
|
|
|
|
+ getProducts (cb) {
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ cb([ /* レスポンスのモック */ ])
|
|
|
|
+ }, 100)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+// 期待されるミューテーションをアクションが呼び出すかをテストするためのヘルパー
|
|
|
|
+const testAction = (action, payload, state, expectedMutations, done) => {
|
|
|
|
+ let count = 0
|
|
|
|
+
|
|
|
|
+ // コミットをモックする
|
|
|
|
+ const commit = (type, payload) => {
|
|
|
|
+ const mutation = expectedMutations[count]
|
|
|
|
+ expect(mutation.type).to.equal(type)
|
|
|
|
+ if (payload) {
|
|
|
|
+ expect(mutation.payload).to.deep.equal(payload)
|
|
|
|
+ }
|
|
|
|
+ count++
|
|
|
|
+ if (count >= expectedMutations.length) {
|
|
|
|
+ done()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // モック化したストアと引数でアクションを呼び出す
|
|
|
|
+ action({ commit, state }, payload)
|
|
|
|
+
|
|
|
|
+ // 呼び出されるべきミューテーションが残っていないか確認する
|
|
|
|
+ if (expectedMutations.length === 0) {
|
|
|
|
+ expect(count).to.equal(0)
|
|
|
|
+ done()
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+describe('actions', () => {
|
|
|
|
+ it('getAllProducts', done => {
|
|
|
|
+ testAction(actions.getAllProducts, null, {}, [
|
|
|
|
+ { type: 'REQUEST_PRODUCTS' },
|
|
|
|
+ { type: 'RECEIVE_PRODUCTS', payload: { /* レスポンスのモック */ } }
|
|
|
|
+ ], done)
|
|
|
|
+ })
|
|
|
|
+})
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### ゲッターのテスト
|
|
|
|
+
|
|
|
|
+もしゲッターが複雑な計算を行っているならば、テストコードを書く価値があります。ゲッターはミューテーションと同様の理由でテストしやすいです。
|
|
|
|
+
|
|
|
|
+ゲッターのテストの例:
|
|
|
|
+
|
|
|
|
+``` js
|
|
|
|
+// getters.js
|
|
|
|
+export const getters = {
|
|
|
|
+ filteredProducts (state, { filterCategory }) {
|
|
|
|
+ return state.products.filter(product => {
|
|
|
|
+ return product.category === filterCategory
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+``` js
|
|
|
|
+// getters.spec.js
|
|
|
|
+import { expect } from 'chai'
|
|
|
|
+import { getters } from './getters'
|
|
|
|
+
|
|
|
|
+describe('getters', () => {
|
|
|
|
+ it('filteredProducts', () => {
|
|
|
|
+ // ステートをモックする
|
|
|
|
+ const state = {
|
|
|
|
+ products: [
|
|
|
|
+ { id: 1, title: 'Apple', category: 'fruit' },
|
|
|
|
+ { id: 2, title: 'Orange', category: 'fruit' },
|
|
|
|
+ { id: 3, title: 'Carrot', category: 'vegetable' }
|
|
|
|
+ ]
|
|
|
|
+ }
|
|
|
|
+ // ゲッターをモックする
|
|
|
|
+ const filterCategory = 'fruit'
|
|
|
|
+
|
|
|
|
+ // ゲッターから結果を受け取る
|
|
|
|
+ const result = getters.filteredProducts(state, { filterCategory })
|
|
|
|
+
|
|
|
|
+ // 結果を検証する
|
|
|
|
+ expect(result).to.deep.equal([
|
|
|
|
+ { id: 1, title: 'Apple', category: 'fruit' },
|
|
|
|
+ { id: 2, title: 'Orange', category: 'fruit' }
|
|
|
|
+ ])
|
|
|
|
+ })
|
|
|
|
+})
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+### テストの実行
|
|
|
|
+
|
|
|
|
+ミューテーションやアクションが適切に書かれている場合は、適切にモック化された後、テストコードはブラウザの API に直接依存関係を持つことはないでしょう。したがって、単純に Webpack でテストをバンドルでき、それを直接 Node で実行できます。別の方法として、本当のブラウザでテストを実行するためには `mocha-loader` または Karma + `karma-webpack` を使用できます。
|
|
|
|
+
|
|
|
|
+#### Node での実行
|
|
|
|
+
|
|
|
|
+以下のような webpack の設定を作成します([`.babelrc`](https://babeljs.io/docs/usage/babelrc/) もあわせて使います):
|
|
|
|
+
|
|
|
|
+``` js
|
|
|
|
+// webpack.config.js
|
|
|
|
+module.exports = {
|
|
|
|
+ entry: './test.js',
|
|
|
|
+ output: {
|
|
|
|
+ path: __dirname,
|
|
|
|
+ filename: 'test-bundle.js'
|
|
|
|
+ },
|
|
|
|
+ module: {
|
|
|
|
+ loaders: [
|
|
|
|
+ {
|
|
|
|
+ test: /\.js$/,
|
|
|
|
+ loader: 'babel',
|
|
|
|
+ exclude: /node_modules/
|
|
|
|
+ }
|
|
|
|
+ ]
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+それから下記コマンドを実行します:
|
|
|
|
+
|
|
|
|
+``` bash
|
|
|
|
+webpack
|
|
|
|
+mocha test-bundle.js
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+#### ブラウザでの実行
|
|
|
|
+
|
|
|
|
+1. `mocha-loader` をインストールする
|
|
|
|
+2. 上記 Webpack 設定から `entry` を `'mocha!babel!./test.js'` に変更する
|
|
|
|
+3. 設定を使用して `webpack-dev-server` を開始する
|
|
|
|
+4. ブラウザで `localhost:8080/webpack-dev-server/test-bundle` を開く
|
|
|
|
+
|
|
|
|
+#### Karma + karma-webpack を使ったブラウザでの実行
|
|
|
|
+
|
|
|
|
+[vue-loader documentation](http://vue-loader.vuejs.org/en/workflow/testing.html) 内のセットアップ方法を参考にしてください。
|