如何通过runSaga / redux-saga获得收益

时间:2019-05-07 18:42:35

标签: testing jasmine mocking jestjs redux-saga

我创建了一个recordSaga函数,其目标是记录在传奇中分配了哪些动作。

export const recordSaga = async (saga, initialAction, state) => {
  const dispatched = [];

  const done = await runSaga(
    {
      dispatch: action => dispatched.push(action),
      getState: () => state,
    },
    saga,
    initialAction,
  ).done;

  return {
    dispatched,
    done,
  };
};

所以我的传奇就是这个

export function* mySaga() {
  const needToSave = yield select(needToSaveDocument);
  if (needToSave) {
    yield put(saveDocument());
    yield take(SAVE_DOCUMENT_SUCCESS);
  }
  yield put(doSomethingElse())
}

我想写两个测试,我希望是这样

describe('mySaga', async () => {
  it('test 1: no need to save', async () => {    
    const state = { needToSave: false }
    const { dispatched } = await recordSaga(mySaga, {}, state);
    expect(dispatched).toEqual([
      doSomethingElse()
    ])
  })
  it('test 2: need to save', async () => {
    const state = { needToSave: true }
    const { dispatched } = await recordSaga(mySaga, {}, state);
    expect(dispatched).toEqual([
      saveDocument(),
      doSomethingElse()
    ])
  })
})

但是,对于测试2,中间有一个take,当然jest(或其女友jasmine)对我大​​叫:Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL. < / p>

我知道这是因为runSaga正在等待take(SAVE_DOCUMENT_SUCCESS),但是我该如何模拟呢?

2 个答案:

答案 0 :(得分:1)

答案import React from 'react' import Auth from '../../Authentication/Auth' import { Redirect, Route } from 'react-router-dom' const PrivateRoute = ({ component: Component, role, ...rest }) => ( <Route {...rest} render={props => { const loggedIn = Auth.isAuthenticated; if (!loggedIn) { // not logged in so redirect to login page with the return url return <Redirect to={{ pathname: '/login', state: { from: props.location } }} /> } // check if route is restricted by role if (Auth.getUserLevel() !== role) { // role not authorised so redirect to home page return <Redirect to={{ pathname: '/home'}} /> } // authorised so return component return <Component {...props} /> }} /> ) export default PrivateRoute;

为什么?

使用import React, { Component } from 'react'; import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom'; import AdminPage from './Containers/AdminPage/AdminPage' import PrivateRoute from './Components/PrivateRoute/PrivateRoute' import Login from './Containers/Login' class App extends Component { cnt=0; render() { return ( <Wrapper> <NavBar /> <Router> <Switch> <Route path="/login"> <Login /> </Route > <PrivateRoute path="/AdminPage" Component={AdminPage} role='sm'/> </Switch> </Router> </Wrapper> ) } } export default App; ,您可以在第一次运行后分派。

如何?

  • 导入stdChannel;
  • 添加到runSaga中的第一个参数;
  • 致电stdChannel().put({type, payload});

示例

什么对我有用

我离开了第一个测试,因为它是预期的最终结果,但是解决方案出现在最后一个测试上。

stdChannel

this answer (about true code, not tests) helped me

答案 1 :(得分:0)

通过查看recordSaga

export const recordSaga = async (saga, initialAction, state) => {

似乎您应该将{type: SAVE_DOCUMENT_SUCCESS}作为第二个参数(即initialAction)传递。那应该触发take效果。