VueJS: Thử nghiệm
Giải phóng thời gian, khai phóng năng lực
Các phần chính mà chúng tôi muốn thử nghiệm đơn vị trong Vuex là các mutation và action.
Thử nghiệm mutation
Rất dễ dàng để kiểm tra các mutation, bởi vì chúng chỉ là các hàm hoàn toàn dựa vào các đối số của chúng. Một mẹo là nếu bạn đang sử dụng các mô-đun ES2015 và đặt các mutation bên trong tệp store.js
của bạn, ngoài việc export mặc định, bạn cũng nên export các mutation dưới dạng export có tên:
const state = { ... } // export `mutations` as a named export export const mutations = { ... } export default new Vuex.Store({ state, mutations })
Ví dụ kiểm tra mutation bằng cách sử dụng Mocha + Chai (bạn có thể sử dụng bất kỳ thư viện framework/assertion nào bạn thích):
// mutations.js export const mutations = { increment: state => state.count++ }
// mutations.spec.js import { expect } from 'chai' import { mutations } from './store' // 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) }) })
#Thử nghiệm action
Các action có thể phức tạp hơn một chút bởi vì chúng có thể gọi ra các API bên ngoài. Khi thử nghiệm action, ta thường cần phải làm một số mức mocking - ví dụ, chúng ta có thể tóm tắt các lời gọi API thành một dịch vụ và giả định dịch vụ đó bên trong các thử nghiệm của chúng ta. Để dễ dàng giả lập các dependecy, ta có thể sử dụng webpack và inject-loader để nạp các tệp thử nghiệm của chúng ta.
Ví dụ kiểm tra action không đồng bộ:
// actions.js import shop from '../api/shop' export const getAllProducts = ({ commit }) => { commit('REQUEST_PRODUCTS') shop.getProducts(products => { commit('RECEIVE_PRODUCTS', products) }) }
// actions.spec.js // use require syntax for inline loaders. // with inject-loader, this returns a module factory // that allows us to inject mocked dependencies. import { expect } from 'chai' const actionsInjector = require('inject-loader!./actions') // create the module with our mocks const actions = actionsInjector({ '../api/shop': { getProducts (cb) { setTimeout(() => { cb([ /* mocked response */ ]) }, 100) } } }) // helper for testing action with expected mutations const testAction = (action, payload, state, expectedMutations, done) => { let count = 0 // mock commit const commit = (type, payload) => { const mutation = expectedMutations[count] try { expect(type).to.equal(mutation.type) if (payload) { expect(payload).to.deep.equal(mutation.payload) } } 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).to.equal(0) done() } } describe('actions', () => { it('getAllProducts', done => { testAction(actions.getAllProducts, null, {}, [ { type: 'REQUEST_PRODUCTS' }, { type: 'RECEIVE_PRODUCTS', payload: { /* mocked response */ } } ], done) }) })
Nếu bạn có gián điệp trong môi trường thử nghiệm của mình (ví dụ: thông qua Sinon.JS ), bạn có thể sử dụng chúng thay vì helper testAction
:
describe('actions', () => { it('getAllProducts', () => { const commit = sinon.spy() const state = {} actions.getAllProducts({ commit, state }) expect(commit.args).to.deep.equal([ ['REQUEST_PRODUCTS'], ['RECEIVE_PRODUCTS', { /* mocked response */ }] ]) }) })
Thử nghiệm getters
Nếu getters của bạn có tính toán phức tạp thì cũng đáng để ta thử nghiệm chúng. Getters cũng rất đơn giản để kiểm tra với cùng một lý do như mutation.
Ví dụ thử nghiệm một 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 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' } ]) }) })
#Chạy thử nghiệm
Nếu mutation và action của bạn được viết đúng cách, các kiểm tra sẽ không có sự phụ thuộc trực tiếp vào API của trình duyệt sau khi mô phỏng đúng cách. Vì vậy, bạn có thể chỉ cần bó các bài kiểm tra với webpack và chạy nó trực tiếp trong Node. Ngoài ra, bạn có thể sử dụng mocha-loader
hoặc Karma + karma-webpack
để chạy thử nghiệm trong trình duyệt thực.
#Chạy trong Node
Tạo cấu hình webpack sau (cùng với proper .babelrc):
// webpack.config.js module.exports = { entry: './test.js', output: { path: __dirname, filename: 'test-bundle.js' }, module: { loaders: [ { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ } ] } }
Sau đó:
webpack mocha test-bundle.js
#Chạy trong trình duyệt
- Cài đặt
mocha-loader
. - Thay đổi cấu hình
entry
webpack ở trên thành'mocha-loader!babel-loader!./test.js'
. - Bắt đầu sử dụng cấu hình
webpack-dev-server
. - Tới
localhost:8080/webpack-dev-server/test-bundle
.
#Chạy trong Trình duyệt với Karma + karma-webpack
Tham khảo ý kiến thiết lập trong tài liệu trình tải vue.
Giải phóng thời gian, khai phóng năng lực