測試一個store,一般的想法都是先看 Vuex 文件:https://vuex.vuejs.org/guide/testing.html,裡面內容是把mutations 、actions個別輸出,分別測試。
不過我的store規模不大,沒把 state、mutations 、actions模塊化,而是直接輸出一個 Vuex實例,所以沒有使用文件裡的測法。
一、測試想法
我的想法很簡單,就是測「actions 處理 response data 的邏輯是否正確」。方法是給 action mock response,然後查看 state 裡來自該 action 的 data 是否正確。
整個測試過程,直接跳過 mutations ,因為 mutations 的內容很單純,不涉及任何邏輯運算。二、模擬假api response
在開始一切測項之前,先在測試文件裡引入要測的store
import store from '@/store/index'
然後模擬 api 的行為,讓它提供 action 假資料:
const data = {
tokens: [
{
product: 37,
tokenId: "123",
company: 53,
datetime_added:"2021-05-28T03:56:24.448Z",
id: 1
},
{
product: 38,
tokenId: "88883627838",
company: 1,
datetime_added: "2021-05-28T08:55:34.163Z",
id: 2
}
]
}
jest.mock('axios')
jset.get.mockResolvedValueOnce(data)
三、寫測試囉
跟測 component 不一樣的是,這邊沒有使用 mount, wrapper 一類的東西。因為在這邊就是測一個js file,不需要弄出一個 vue 實例。it('Api: handel response', async() = {
const answer = [
{
productId: 37,
companyId: 53,
addTime: "2021-05-28T03:56:24.448Z",
transactionId: 1
},
{
productId: 38,
companyId: 1,
addTime: "2021-05-28T08:55:34.163Z",
transactionId: 2 }
]
await store.dispatch("getTransaction");
const transaction = store.state.transaction;
expect(dongles).toEqual(answer); })
})
第二部分,就是執行 action,讓它call 假api。
最後一部分,撈出 state 裡的 data,判段它與第一部分定義的內容是否一致
大概就這樣完成它了。
四、mockRejectedValue
雖然大致完成了一個測試,但若要測試所有 actions,和所有 handle response 的邏輯,還需顧及返回error的部分:axios.get.mockRejectedValueOnce(new Error(`mock err:${url}`));
至於再寫一個測試文件,專門讓 jest.mock('axios')模擬返回error的情況則更簡單。開一個新文件,把 jest.mock改寫成 return Promise.reject 就行了:
其他就是,寫測試常常需要用模擬的方式來取代依賴項目,很容易遇到「某個東西不存在」的情況(因為 jest.fn 不會自動模擬所有被模擬對象的細節)。這時就兵來將擋,水來土淹,缺什麼我就會在 jset.mock 裡塞什麼,務必讓測試能順利跑起來就是了。
例如這次專案,我有設置 axios.defaults.withCredentials = true。在測試的 jest.mock('axios')裡,我也放了一個 { withCredentials: true }。
還有很常見的 router.push,該怎麼 mock 就怎麼 mock。
五、小結
我認為這個測試的優點是原理簡單,至於是不是最佳解,我自己也不太確定。因為只關注 actions 和 state,跳過了mutations,所以萬一測試失敗,它沒有辦法很直觀地反應是 action、mutations還是 state 的問題。不過我的 mutations 內容很簡單,只是收data、放data到state裡而已,不至於因此困擾。
最後,我總共測了5個 handle api 的 actions。假如store 的功能規模比較大的話,就不適合像這樣引入整個 Vuex.Store 實例了,屆時我應該會把 store 拆成 modules,然後分別用不同的文件測試。
留言
張貼留言