Redux-Saga - redux-saga-test-plan 測試範例
最近在專案中第一次使用 redux-saga ,對一個 saga 寫測試的時候,看到既有的一些 saga 測試使用 redux-saga-test-plan。在閱讀文件的範例過程中,把 testSaga
和 expectSaga
兩個測試用法搞糊塗,於是仔細地讀了裡面的說明。兩者的差別如下:
testSaga
: 在乎 saga 的順序、每一個被 yield 的 effect 樣貌對不對。expectSaga
: 在乎 saga 的結果對不對。
利用範例說明
下面的範例是在描述用戶在登入成功時,要接著去把用戶資訊拉回來,更新到 redux store 的 state 裡面。
sagas/auth/selectors.js
1 | export const getToken = state => state.auth.token; |
sagas/auth/actions.js
1 | export const LOGIN_SUCCESSFULLY = 'LOGIN_SUCCESSFULLY'; |
sagas/user/actions.js
1 | export const RESET_USER_INFO = 'RESET_USER_INFO'; |
sagas/user/reducers.js
1 | import { RESET_USER_INFO, SET_USER_INFO, LOAD_USER_INFO_ERROR } from './actions'; |
sagas/user/index.js
1 | import { takeLatest, select } from 'redux-saga/effects'; |
testSaga 用法
因為需要確保 saga 的執行順序,以及每一個被 yield 的 effect 如同預期,所以用法有幾個原則:
- 先執行
testSaga(saga, ...args)
- 再按照順序執行 effects ,每一個 effect 執行之前都要先做
.next()
到達當前的 effect - 最後要執行
.isDone()
,看看這個 saga 是否已經執行完畢
下面的程式碼分別針對 saga()
和 loadUserInfo
兩個 saga 做測試,很單純地只是在測試運作的順序有沒有按照預期那樣而已。如果把 loadUserInfo
的測試範圍涵蓋到 error 的情況,就必須要開不同的 testSaga
去驗證,可參考官方文件的範例。
sagas/user.spec.js
1 | import { testSaga } from 'redux-saga-test-plan'; |
expectSaga 用法
在使用 expectSaga
的時候,因為目的是要確保模擬的輸入參數、設定的情境,產出的結果能夠符合預期。因此,用法上有幾個原則:
- 會影響結果的 effect 都要測試到
- 只需要 mock saga 在執行每一個 effect 的結果
- 用
.provide()
可以 mock 固定的 effect 結果,也可以 mock 動態的結果 - 最後再執行
.run()
下面是官方範例:
1 | import { call, put, take } from 'redux-saga/effects'; |
結論
testSaga
目的在於 branching 是否如預期expectSaga
目的在於結果是否如預期