iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 23
1
Modern Web

Vue 怎麼寫測試系列 第 23

Day 23. 實作一個電商網站 - 購物車

前言

加入購物車的按鈕要怎麼寫測試?
要用到 vuex 嗎?
如果用的話,actions, state, mutations 要怎麼測?
每次開發總是想得太遠,做得太少?

正文

寫測試的目的之一,我想是你有多少能力測多少事
已最小可行性當作出發點吧

所以首先當然是拋開 vuex,

設想一下,當我們今天要加入購物車
最簡單的作法是什麼?

就是在 data property 多一個地方可以存就好了
然後,有個按鈕會把選到的產品 id 加到購物車的 Object 裡面

所以我們一開始的測試可以這樣寫

it('按加入,要把產品 id 和數量加到購物車', () => {
  expectTo.click('.add-to-cart-button')
  expect(wrapper.vm.cart.products.length).toEqual(1)
  expect(wrapper.vm.cart.products[0].id).toEqual(1)
  expect(wrapper.vm.cart.products[0].count).toEqual(1)
})

it('如果產品已經在購物車,數量 +1', () => {
  expectTo.click('.add-to-cart-button')
  expect(wrapper.vm.cart.products.length).toEqual(1)
  expect(wrapper.vm.cart.products[0].id).toEqual(1)
  expect(wrapper.vm.cart.products[0].count).toEqual(1)

  expectTo.click('.add-to-cart-button')
  expectTo.click('.add-to-cart-button')
  expectTo.click('.add-to-cart-button')
  expect(wrapper.vm.cart.products.length).toEqual(1)
  expect(wrapper.vm.cart.products[0].id).toEqual(1)
  expect(wrapper.vm.cart.products[0].count).toEqual(4)
})
<button class="add-to-cart-button" @click="addToCart"> 加入購物車</button>

methods: {
    addToCart () {
        // 加到 cart object
    }
},
data: {
    ...
    cart: {
      products: []
    },
}

有了這個雛形之後,我想多做一點改變
把購物車用 vuex 去實作

在 /store 裡面新增一個 index.js
簡單放一點功能

export const state = () => ({
  cart: {
    products: []
  }
})

export const mutations = {
  add (state, productId) {
    let product = state.cart.products.find(
        product => product.id === productId
    )
    
    product ? 
        product.count += 1 : 
        this.cart.products.push({id: productId, count: 1})
  }
}

那我們的原本加入購物車的邏輯就要調整
回去 LandingPage.vue, 把 vuex 設定近來

import { mapState, mapMutations } from 'vuex'

export default {

    computed: {
        ...mapState(['cart'])
        
        // 省略其他的內容
    },

    methods: {
        ...mapMutations(['add']),

        // 這樣就可以直接使用了
        addToCart () {
            this.add(this.selectedProductId)
        }
        
        // 省略其他的內容
    }
}

這時候會發現我們的測試壞掉了,這是正常的
我們的測試只是沒設定 Vuex 而已
這邊我們要怎麼修呢

先讓 vue 知道我們要用 vuex

import { mount, shallow, createLocalVue } from 'vue-test-utils'
import Vuex from 'vuex'

const localVue = createLocalVue()
localVue.use(Vuex)

再來在 beforeEach 的區塊,mock vuex 的所有內容

beforeEach(() => {

  mutations = {
    // 直接用個 stub function
    add: jest.fn(),
  }
  store = new Vuex.Store({
    state: {}, // 根本連什麼資料都不用設定
    mutations
  })
}

然後我們的測試,只需要確認我們的 stub function 有被使用就好

it('按加入,要觸發加入購物車的 action', () => {
  expectTo.click('.add-to-cart-button')
  expect(mutations.add).toHaveBeenCalled()
})

murmur

基本上我們把功能 mock 住,就代表我們信任那個 module
這個信任是很盲目的,還有時間的話 vuex 要單獨自己寫測試
這邊就建議用嚴格的 unit testing
畢竟是單純的邏輯, 跟畫面沒有關係


上一篇
Day 22. 實作一個電商網站 - 多方案的產品選擇
下一篇
Day 24. 實作一個電商網站 - 購物車(二)
系列文
Vue 怎麼寫測試30

尚未有邦友留言

立即登入留言