测试 redux-saga 的 all 效果的最佳方法是什么?

What's the best way to test redux-saga's `all` effect?

我有一个 saga,目前有一个 yield all(...),我正在尝试弄清楚如何测试以查看我实际上是在使用正确的函数调用 all()。这是我正在使用的精简版:

function* start() {
  // I'd prefer not to start the status polling and the listening for
  // the cancellation until after the request has been submitted, but
  // I'm having trouble figuring out how to do that. So I'm just going
  // to listen for 'em all up front here until I'm smarter.
  yield all([
    waitForCreateRequest(),
    waitForPollStatus(),
    waitForCancelRequest(),
  ])
}

function* waitForCreateRequest() {
  while ( true ) {  
    try {
      const { payload } = yield take('CREATE_REQUEST')
      // ...
    } catch ( error ) {
      // ...
    }
  }
}

function* waitForPollStatus() {
  while ( true ) {  
    try {
      const { payload } = yield take('POLL_STATUS')
      // ...
    } catch ( error ) {
      // ...
    }
  }
}

function* waitForCancelRequest() {
  while ( true ) {  
    try {
      yield take('CANCEL_REQUEST')
      // ...
    } catch ( error ) {
      // ...
    }
  }
}

我写的测试(使用 Mocha 和 bdd-lazy-var)是这样的:

describe('MySaga', () => {
  describe('*start()', () => {
    subject(start())

    it('calls `all()` with the correct functions', () => {
      expect($subject.next().value).to.eql(all([
        waitForSubmitExportRequest(),
        waitForPollExportStatus(),
        waitForCancelExportRequest(),
      ]))
    })
  })
})

没有输出——它只是挂起...然后我得到一个 "JavaScript heap out of memory" 错误。

如果我 console.log($subject.next().value) 而不是:

describe('MySaga', () => {
  describe('*start()', () => {
    subject(start())

    it.only('foo', () => {
      console.log($subject.next().value)
    })
  })
})

这是我得到的:

  MySaga
    *start()
{ '@@redux-saga/IO': true,
  ALL: 
   [ GeneratorFunctionPrototype { _invoke: [Function: invoke] },
     GeneratorFunctionPrototype { _invoke: [Function: invoke] },
     GeneratorFunctionPrototype { _invoke: [Function: invoke] } ] }
      ✓ foo

所以我不确定这里发生了什么。

无数 Google 搜索并没有真正找到任何有用的东西,我找到的最接近的 SO post (how to test redux-saga all effect using jest) 也没有帮助。

您的 start 函数不是生成器函数,这是一个拼写错误吗?

总之。你能尝试像这样重写你的 start 函数吗:

function* start() {
  yield all([
    call(waitForCreateRequest),
    call(waitForPollStatus),
    call(waitForCancelRequest),
  ])
}

现在您的测试可能如下所示:

it('calls `all()` with the correct functions', () => {
  expect($subject.next().value).to.eql(all([
    call(waitForSubmitExportRequest),
    call(waitForPollExportStatus),
    call(waitForCancelExportRequest),
  ]))
})