使用runSaga进行延误和延误测试

时间:2019-05-15 12:28:15

标签: javascript redux redux-saga

如果我使用以下形式的传奇:

function * sagaWorker() {
  yield put(START_ACTION)
  yield take(WAIT_FOR_ACTION)
  yield delay(100)
  yield put(END_ACTION)
}

我可以像这样使用runSaga成功地测试它:

step('saga passes the tests', async () => {
  const channel = stdChannel()
  const dispatched = []
  const options = {
    dispatch: action => dispatched.push(action),
    getState: () => {},
    channel
  }
  const task = runSaga(options, sagaWorker)
  channel.put(WAIT_FOR_ACTION)
  await task.toPromise()
  expect(dispatched).to.deep.eql([START_ACTION, END_ACTION])
})

但是,如果我将延迟时间移到汇整的前面:

function * sagaWorker() {
  yield put(START_ACTION)
  yield delay(100)
  yield take(WAIT_FOR_ACTION)
  yield put(END_ACTION)
}

现在,传奇故事没有完成并超时-它到达了take,但动作从未到达频道。

是否可以使用此表格进行测试?我怀疑我可以通过call而不是delay直接yield来使它们工作,但是我想知道如何不这样做而使它工作(如果可能的话) )。

1 个答案:

答案 0 :(得分:4)

使用yield call(() => myPromiseyDelay(500))不会在这里保存您。派遣时仍然没有什么可以注意到“丢失”的动作。

发布WAIT_FOR_ACTION时,传奇故事在yield delay上处于屈服状态。这里没有行动的队列,因此到yield take(WAIT_FOR_ACTION)为止,WAIT_FOR_ACTION行动早已被分派,您上面提到的任何佐贺逻辑都没有注意到(没有有效的{ {1}}进行操作。

请考虑设置一个actionChannel来捕获这些未监听的操作。 take完成后,它们将在渠道中排队等待使用。

所以,像这样:

delay

因此,将所有内容组合为非伪代码:

function * sagaWorker() {
  const channel = yield actionChannel(WAIT_FOR_ACTION)
  yield put(START_ACTION)
  yield delay(100)
  yield take(channel)
  yield put(END_ACTION)
}
const {
  runSaga,
  stdChannel,
  effects: {
    take,
    put,
    actionChannel,
    delay
  }
} = window.ReduxSaga

const WAIT_FOR_ACTION = "WAIT_FOR_ACTION";
const START_ACTION = "START_ACTION";
const END_ACTION = "END_ACTION";

(async() => {
  const channel = stdChannel();
  const dispatched = [];
  const options = {
    dispatch: action => dispatched.push(action),
    getState: () => {},
    channel
  };
  const task = runSaga(options, sagaWorker);
  channel.put({
    type: WAIT_FOR_ACTION
  });
  await task.toPromise();
  console.log(dispatched);
})();

function* sagaWorker() {
  const channel = yield actionChannel(WAIT_FOR_ACTION);
  yield put({
    type: START_ACTION
  });
  yield delay(100);
  yield take(channel);
  yield put({
    type: END_ACTION
  });
}