单元测试Redux Sagas

时间:2017-02-09 19:23:23

标签: unit-testing reactjs testing redux redux-saga

我已经按照Redux Sagas的文档编写了一组测试,但是对我来说它们看起来非常脆弱。每当我更新任何传奇故事中的逻辑时,我的测试都会失败。这引起了我脑海中的警钟,让我觉得我做错了什么。

这是一个示例传奇,它与API通信以加载用户的配置文件并将其存储在Redux状态:

export function* userAuthCheck() {
    try {
        yield put({ type: START_HTTP });

        const me = yield apply(user, user.me);
        const organisations = yield apply(user, user.organisations, [me.body.data.id]);

        yield put({
            type: USER_AUTH_SUCCESS,
            redirect: true,
            state: {
                account: me.body.data,
                organisations: organisations.body.data,
            },
        });
    } catch (error) {
        yield put({ type: USER_AUTH_REFRESH });
    } finally {
        yield put({ type: COMPLETE_HTTP });
    }
}

以下是相应的测试:

it('can successfully call the API', () => {
    const generator = userAuthCheck();

    expect(generator.next().value).toEqual(put({ type: START_HTTP }));
    expect(generator.next().value).toEqual(call(user.me));

    expect(generator.next().value).toEqual(put({
        type: USER_AUTH_SUCCESS,
        state: { user: undefined },
    }));

    expect(generator.next().value).toEqual(put({ type: COMPLETE_HTTP }));
});

你可能会注意到测试实际上会因为运行而失败,因为我没有对它进行更新,因为我最近对saga做了一些更新。这就是让我开始思考这条思路的事情。

有没有更好的方法来测试我的传奇?是否可以从头到尾运行它们,模拟不同的API响应并断言正确的事情被分派到状态?

这些是我一直关注的文档:https://redux-saga.github.io/redux-saga/docs/introduction/BeginnerTutorial.html

2 个答案:

答案 0 :(得分:3)

我喜欢通过嘲笑商店来测试它,所以对于你的例子它是这样的:

import configureMockStore from "redux-mock-store";
import createSagaMiddleware from "redux-saga";
import rootSaga from "pathToRootSaga/rootSaga";
import {userAuthCheckActionCreator} from "yourPath/UserActionCreators"; 

it('can successfully call the API', () => {
  const sagaMiddleware = createSagaMiddleware();
  const mockStore = configureMockStore([sagaMiddleware]);
  const store = mockStore({});
  sagaMiddleware.run(rootSaga);

  const expectedActions = [
    {
      type: START_HTTP
    },
    {
      type: USER_AUTH_SUCCESS,
      redirect: true,
      state: {
          account: me.body.data,
          organisations: organisations.body.data,
      }
    },
    { 
      type: COMPLETE_HTTP 
    }
  ];

  store.dispatch(userAuthCheckActionCreator());
  expect(store.getActions()).toEqual(expectedActions);
});

我喜欢这种方法的是,我可以清楚地看到整个行动顺序是否按预期顺序发送。此外,一切都发生在模拟商店的背景下,让Saga中间件调度动作,因此您不需要操纵生成器功能。

答案 1 :(得分:1)

issue #518的redux-saga问题跟踪器中有一个很长的问题主题。所以没有一个商定的正确的测试方法,但是有一些选择,我会说最好的方法可能取决于你正在测试的是什么。

上面的帖子中提到了一些测试助手包:

the redux-saga test suite中还有一些很好的例子可供学习。