testing.md 3.5 KB

测试

Mutations 很容易测试,因为它仅仅是一个带参数的函数。相反测试 Actions 就比较难,因为 actions 会调用其它的一些 APIs. 测试 actions 的时候我们需要做一定的 mocking —— 比如说把 API 调用抽象成一个 service,然后测试的时候用另一个 mock 的 service. 为了方便地 mock,我们可以使用 Webpack 和 inject-loader 打包测试文件。

If your mutations and actions are written properly, the tests should have no direct dependency on Browser APIs after proper mocking. Thus you can simply bundle the tests with Webpack and run it directly in Node. Alternatively, you can use mocha-loader or Karma + karma-webpack to run the tests in real browsers.

???

下面是用 Mocha + Chai 测试 mutation 的例子(你可以用任何你喜欢的测试工具):

// mutations.js
export const INCREMENT = state => state.count++
// mutations.spec.js
import { expect } from 'chai'
import { INCREMENT } from './mutations'

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

测试异步 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

// 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!babel!./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, state, expectedMutations, done) => {
  let count = 0
  const mockedDispatch = (name, payload) => {
    const mutation = expectedMutations[count]
    expect(mutation.name).to.equal(name)
    if (payload) {
      expect(mutation.payload).to.deep.equal(payload)
    }
    count++
    if (count >= expectedMutations.length) {
      done()
    }
  }
  action(mockedDispatch, state)
}

describe('actions', () => {
  it('getAllProducts', done => {
    testAction(actions.getAllProducts(), {}, [
      { name: 'REQUEST_PRODUCTS' },
      { name: 'RECEIVE_PRODUCTS', payload: [ /* mocked response */ ] }
    ], done)
  })
})

在 Node 中运行

创建以下 webpack 配置:

module.exports = {
  entry: './test.js',
  output: {
    path: __dirname,
    filename: 'test-bundle.js'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel',
        exclude: /node_modules/
      }
    ]
  },
  babel: {
    presets: ['es2015']
  }
}

然后:

webpack
mocha test-bundle.js

在浏览器运行

  1. Install mocha-loader
  2. Change the entry from the Webpack config above to 'mocha!babel!./test.js'.
  3. Start webpack-dev-server using the config
  4. Go to localhost:8080/webpack-dev-server/test-bundle.

  5. 安装 mocha-loader

  6. webpack 配置中的 entry 改成 'mocha!babel!./test.js'

  7. 用以上配置启动 webpack-dev-server

  8. 打开 localhost:8080/webpack-dev-server/test-bundle.