首页 > 解决方案 > 在 vuex 操作中模拟 api 调用

问题描述

我有一个带有动作的 vuex 商店。

//actions.js
import api from '@/api.js'

export default {
  getAllProducts ({commit}) {
    // call the api and return a promise with the products

    api.fetchAllProducts().then((products) => {
        commit('getAllProducts', products)
    })  
}

现在来测试一下!

// actions.spec.js
import actions from './actions.js'
import api from './api.js'

describe('shop actions', () => {

  it('calls api and fetches products', () => {
    let state = {items: []}
    let commit = sinon.spy()
    let stub = sinon.stub(api, 'fetchAllProducts')
    stub.resolves('a product')

    actions.getAllProducts({commit, state})

    expect(commit.args).to.deep.equal([
        ['SET_ALL_PRODUCTS', 'a product']
    ])  
  })
})

这是我迄今为止的尝试。由于几个原因,它不起作用。

  1. api 函数上的 sinon 存根不会同时存根在 actions.js 上导入的 api。
  2. api函数返回一个promise,所以测试而不是等待它解决只是返回断言,所以commit.args将永远是[]

关于如何测试 vuex 操作的任何建议。我认为主要的困难在于对 api 模块进行存根,而且我很困惑。任何建议表示赞赏:)

标签: unit-testingvue.jsvuex

解决方案


该操作getAllProducts应返回承诺。

getAllProducts ({ commit }) {
  return api.fetchAllProducts().then((products) => {
    commit('SET_ALL_PRODUCTS', products)
  })
}

那么你的测试代码应该是这样的:

describe('shop actions', () => {
 it('calls api and fetches products', done => {
   let state = {items: []}
   let commit = sinon.spy()
   let stub = sinon.stub(api, 'fetchAllProducts')
   stub.resolves('a product')

   actions.getAllProducts({commit, state}).then(() => {
     expect(commit.args).to.deep.equal([
       ['SET_ALL_PRODUCTS', 'a product']
     ])
     done()
    })
   stub.restore()
   })
})

此外,如果您没有从操作中返回承诺,我们可以使用 async/await。

 it('calls api and fetches products', async () => {
   let state = {items: []}
   let commit = sinon.spy()
   let stub = sinon.stub(api, 'fetchAllProducts')
   stub.resolves('a product')

   await actions.getAllProducts({commit, state})
   expect(commit.args).to.deep.equal([
       ['SET_ALL_PRODUCTS', 'a product']
     ])
   stub.restore()
 })

推荐阅读