©
This document uses PHP Chinese website manual Release
我们主要针对Vuex中的mutaions 和actions进行单元测试。
Mutations 很容易被测试,因为它们仅仅是一些完全依赖参数的函数。小技巧是,如果你在 store.js
文件中定义了 mutations,并且使用 ES2015 模块功能默认输出,那么你仍然可以给 mutations 取个变量名然后把它输出去:
const state = { ... } //取个变量名并输出mutations export const mutations = { ... } export default new Vuex.Store({ state, mutations })
以下为使用 Mocha + chai 测试 mutation 的例子(实际上你可以用任何你喜欢测试框架)
// mutations.js export const mutations = { increment: state => state.count++ }
// mutations.spec.js import { expect } from 'chai' 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).to.equal(1) }) })
Actions 可能会更加棘手一些,因为他们可能要求请求外部API.
当测试actions时,我们通常需要增加mocking服务层——例如,我们可以把API调用抽象成服务,然后我们在测试中模拟这种服务。为了便于解决mock的依赖关系,可以用 Webpack 和 inject-loader 打包测试文件。
异步action测试示例:
// actions.js import shop from '../api/shop' export const getAllProducts = ({ dispatch }) => { dispatch('REQUEST_PRODUCTS') shop.getProducts(products => { dispatch('RECEIVE_PRODUCTS', products) }) }
// actions.spec.js // 使用 require 语法处理内联loaders //inject-loader,返回一个模块工厂 //让我们能够注入mocked的依赖关系。 import { expect } from 'chai' const actionsInjector = require('inject!./actions') //使用mocks创建模块 const actions = actionsInjector({ '../api/shop': { getProducts (cb) { setTimeout(() => { cb([ /* mocked response */ ]) }, 100) } } }) //用指定的mutatios测试action的辅助函数 const testAction = (action, args, state, expectedMutations, done) => { let count = 0 // mock 提交 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() } } // 用模拟的 store 和参数调用 action action({ commit, state }, ...args) // 检查是否没有 mutation 被 dispatch if (expectedMutations.length === 0) { expect(count).to.equal(0) done() } } describe('actions', () => { it('getAllProducts', done => { testAction(actions.getAllProducts, [], {}, [ { type: 'REQUEST_PRODUCTS' }, { type: 'RECEIVE_PRODUCTS', payload: { /* mocked response */ } } ], done) }) })
如果你的getters方法很复杂,那么你得测试他们。测试Getter 方法和测试mutations一样非常简单!
测试getter实例:
// getters.js export const getters = { filteredProducts (state, { filterCategory }) { return state.products.filter(product => { return product.category === filterCategory }) } }
// getters.spec.js import { expect } from 'chai' import { getters } from './getters' describe('getters', () => { it('filteredProducts', () => { // mock 状态 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' // 从getter中取回值 const result = getters.filteredProducts(state, { filterCategory }) // 声明返回值 expect(result).to.deep.equal([ { id: 1, title: 'Apple', category: 'fruit' }, { id: 2, title: 'Orange', category: 'fruit' } ]) }) })
如果你的 mutations 和 actions 已经正确,后面应该在适合的mocking上浏览器测试API的依赖关系。
创建下面的webpack配置(加上适合.babelrc
):
// webpack.config.js module.exports = { entry: './test.js', output: { path: __dirname, filename: 'test-bundle.js' }, module: { loaders: [ { test: /\.js$/, loader: 'babel', exclude: /node_modules/ } ] } }
然后:
webpack mocha test-bundle.js
安装 mocha-loader
把上述 webpack 配置中的 entry 改成 ‘mocha!babel!./test.js’
用以上配置启动 webpack-dev-server
访问 localhost:8080/webpack-dev-server/test-bundle
.
详细的安装咨询见vue-loader documentation.