【问题标题】:how to receive a take with runSaga / redux-saga如何使用 runSaga / redux-saga 接收拍摄
【发布时间】:2019-05-07 18:42:35
【问题描述】:

我创建了一个 recordSaga 函数,它的目标是记录在 saga 期间调度了哪些动作。

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.

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

【问题讨论】:

    标签: testing jasmine mocking jestjs redux-saga


    【解决方案1】:

    答案stdChannel().put({type, payload})

    为什么?

    使用stdChannel,您可以在第一次运行后调度。

    如何?

    • 导入标准频道;
    • 添加到 runSaga 中的第一个参数;
    • 致电stdChannel().put(SAVE_DOCUMENT_SUCCESS);

    示例

    什么对我有用

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

    
      import { runSaga, stdchannel } from 'redux-saga'
      let dispatchedActions = [];
      let channel;
      let fakeStore;
    
      beforeEach(() => {
        channel = stdChannel(); // you have to declare the channel to have access to it later
        fakeStore = {
          channel, // add it to the store in runSaga
          getState: () => "initial",
          dispatch: (action) => dispatchedActions.push(action),
        };
      });
    
      afterEach(() => {
        global.fetch.mockClear();
      });
    
     it("executes getData correctly", async () => {
        await runSaga(fakeStore, getData, getAsyncData("test")).toPromise();
        expect(global.fetch.mock.calls.length).toEqual(1);
        expect(dispatchedActions[0]).toEqual(setData(set_value));
      });
    
      it("triggers takeLatest and call getData(), but unfortunately doesn't resolve promise", async () => {
        await runSaga(fakeStore, rootSaga)// .toPromise() cannot be used here, as will throw Timeout error
        channel.put(getAsyncData("test")); // if remove this line, the next 2 expects() will fail
        expect(global.fetch.mock.calls.length).toEqual(1);
        // expect(dispatchedActions[1]).toEqual(setData(set_value)); // will fail here, but pass on the next it()
      });
    
      it("takes the promised data from test above", () => {
        expect(dispatchedActions[1]).toEqual(setData(set_value));
      });
    

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

    【讨论】:

      【解决方案2】:

      通过查看recordSaga:

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

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

      【讨论】:

      • 好吧,它不是initialAction,所以它对我不起作用。我尝试了您的解决方案,但出现了同样的错误
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-04
      • 1970-01-01
      • 2018-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多