redux-saga-test-plan expectSaga- 使用状态分支测试 reducer

redux-saga-test-plan expectSaga- Testing reducer with state branch

我在正确测试我的 saga 时遇到了一些麻烦。问题源于这样一个事实,即当 运行 saga 时,减速器安装在 state: {...initialState} 而我的 saga select 效果期望减速器安装在 state: {authentication: {...initialState}}

因此我无法完全测试 reducer/saga 组合,因为最终状态对象的形状与商店的实际形状不一致。

正在测试的传奇:

export default function* rootAuthenticationSaga() {
  while (true) {
      refreshToken = yield select((state: ApplicationRootState) => state.authentication.refreshToken);
      ... more code here
}

我的一个测试如下:

    test('logs the user in if they provide a valid email and password', () => {
      const mockRefreshPoller = createMockTask();
      const initialState = {
        accessToken: '',
        refreshToken: '',
        userId: '',
      }
      return expectSaga(rootAuthenticationSaga)
        .withReducer(authenticationReducer, initialState)
        .provide([
          // some mock providers set up here
        ])
        // ...more asserts here
        .put(authenticationActions.saveTokens({accessToken: 'VALID_ACCESS_TOKEN', refreshToken: 'VALID_REFRESH_TOKEN'}))
        .hasFinalState({
           accessToken: 'VALID_ACCESS_TOKEN',
           refreshToken: 'VALID_REFRESH_TOKEN',
           userId: 'USER_ID',
        })
        .dispatch(authenticationActions.login.request({email: 'VALID_EMAIL', password: 'VALID_PASSWORD'}))
        .run()
    });

在上面的测试中,select() 失败了,因为正确的路径(通过 withReducer 注入)在 state.refreshToken 而不是 state.authentication.refreshToken

如果我通过 withState({authentication: {refreshToken, ...}}) 注入状态,那么 select 会按预期工作,但是所有 reducer 操作都是针对状态根发生的,我的最终状态具有(不正确的)形状:

{state: 
  authentication: {
    refreshToken: '',
    ...
  },
  refreshToken: 'VALID_REFRESH_TOKEN',
  ...
}

这样做的诀窍是 "mount" 通过创建

右边 "branch" 的减速器
const reducerUnderTest = createReducer({
  authentication: authenticationReducer,
})

并以正确的形状状态将其传递到 withReducer(reducerUnderTest, {authentication: {...initialState}}