如何對 Vue 的 Filter 進行 Unit Test ?
若在 Component 使用 Filter,對 Component 進行 Unit Test 時,就必須對 Filter 加以 Mock,同時也討論如何單獨對 Filter 進行 Unit Test。
Version
Vue 2.6.6
Vue CLI 3.5.1
Vue-test-utils 1.0.0-beta.29
Filter
money.js
export const dollar = val => `$${val.toLocaleString()}`;
建立 dollar()
filter,目的將 Number 每 三位數
加上逗點,並加上 $
prefix。
Component
App.vue
<template> <div id="app"> <h1>{{ balance | dollar }}</h1> </div> </template> <script> import { dollar } from '@/filters/money'; export default { name: 'app', data: () => ({ balance: 1234 }), filters: { dollar, }, } </script>
在 HTML template 使用 dollar()
filter。
第 8 行
import { dollar } from '@/filters/money';
將 dollar()
filter import 進來。
15 行
filters: { dollar, },
宣告 dollar()
filter。
第 3 行
<h1>{{ balance | dollar }}</h1>
在 HTML template 使用 dollar()
filter,使用 |
pipe operator 將 balance
data 傳給 dollar
filter。
Unit Test
Filter
dollar.filter.spec.js
import { dollar } from '@/filters/money'; test('dollar() filter', () => { /** arrange */ const stub = 1234; /** act */ const result = dollar(stub); /** assert */ expect(result).toEqual('$1,234'); });
Filter 本質只是 function,若要對 filter 進行 unit test,就把它當成普通 function 測試即可。
第 1 行
import { dollar } from '@/filters/money';
將要測試的 dollar()
import 進來。
第 3 行
test('dollar() filter', () => { /** arrange */ /** act */ /** assert */ });
所有的 unit test 都包在 test()
的第二個引數,以 Arrow Function 表示。
test()
的第一個引數為 description,可描述 test case。
一樣使用 3A 原則寫 unit test。
第 4 行
/** arrange */ const stub = 1234;
建立要測試的 stub。
第 7 行
/** act */ const result = dollar(stub);
實際執 dollar()
filter,並傳入剛剛在 arrange 建立的 stub。
10 行
/** assert */ expect(result).toEqual('$1,234');
實際測試 dollar()
filter 回傳結果是否如預期。
$ yarn test:unit
Component
若 component 使用了 filter,而要對 component 其他部分進行 unit test 時,必須將 filter 加以 mock。
app.component.spec.js
import { shallowMount, createLocalVue } from '@vue/test-utils'; import App from '@/App.vue'; test('App component', () => { /** arrange */ const stub = x => x; /** act */ const localView = createLocalVue(); const wrapper = shallowMount(App, { localView, filters: { dollar: jest.fn(stub), } }); /** assert */ expect(wrapper.find('h1').text()).toEqual('1234'); });
第 1 行
import { shallowMount, createLocalVue } from '@vue/test-utils';
直接 import Vue Test Utiles 兩個最重要的 shallowMount()
與 createLocalVue()
,稍後會說明。
第 2 行
import App from '@/App.vue';
將我們要測試的 App
component import 進來。
第 4 行
test('App component', () => { /** arrange */ /** act */ /** assert */ });
所有的 unit test 都包在 test()
的第二個引數,以 arrow function 表示。
test()
的第一個引數為 description,可描述 test case。
一樣使用 3A 原則寫 unit test。
第 5 行
/** arrange */ const stub = x => x;
建立我們要 mock 的 function,由於不希望有任何效果,直接 output 等於 input 即可。
第 8 行
/** act */ const localView = createLocalVue(); const wrapper = shallowMount(App, { localView, filters: { dollar: jest.fn(stub), } });
使用 Vue Test Utils 的 createLocalVue()
建立測試用的 Vue instance。
使用 shallowMount()
建立假 component 測試,並將 localVue
傳入,此外還要重新宣告 dollar()
filter,並指定為以 stub 所建立的 mock function。
17 行
/** assert */ expect(wrapper.find('h1').text()).toEqual('1234');
由於 filter 是用在 HTML template,因此直接對 HTML template 驗證結果是否如預期。
$ yarn test:unit
Conclusion
shallowMount()
Sample Code
完整範例可以在我的 GitHub 上找到