在React/Redux应用程序中测试提取操作 [英] Testing fetch action in react/redux app

查看:69
本文介绍了在React/Redux应用程序中测试提取操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从单元测试和Jest开始.我想要的是从数据库中获取一些资源后测试操作的响应.

Im starting with unit testing and Jest. What I want is to test the action's response after fetching some resources from the db.

这是动作代码:

export function loadPortlets() {
   return function(dispatch) {
     return portletApi.getAllPortlets().then(response => {
       dispatch(loadPortletsSuccess(response));
       dispatch(hideLoading());
     }).catch(error => {
        dispatch({ type: null, error: error });
        dispatch(hideLoading());
        throw(error);
     });
   };
}

此代码正在从以下位置获取数据:

This code is fetching data from:

  static getAllPortlets() {

    return fetch(`${API_HOST + API_URI}?${RES_TYPE}`)
      .then(response =>
        response.json().then(json => {
          if (!response.ok) {
            return Promise.reject(json);
          }

          return json;
        })
      );
}

这是测试:

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import fetch from 'isomorphic-fetch';
import fetchMock from 'fetch-mock';
import * as actions from '../portletActions';
import * as types from '../actionTypes';

const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);

const mockResponse = (status, statusText, response) => {
  return new window.Response(response, {
    status: status,
    statusText: statusText,
    headers: {
      'Content-type': 'application/json'
    }
  });
};

describe('async actions', () => {
  afterEach(() => {
    fetchMock.reset();
    fetchMock.restore();
  })

  it('calls request and success actions if the fetch response was successful', () => {
    window.fetch = jest.fn().mockImplementation(() =>
      Promise.resolve(mockResponse(200, null, [{ portlets: ['do something'] }])));

    const store = mockStore({ portlets: []});

    return store.dispatch(actions.loadPortlets())
      .then(() => {
        const expectedActions = store.getActions();
        expect(expectedActions[0]).toContain({ type: types.LOAD_PORTLETS_SUCCESS });
      })
  });

});

这是运行测试的结果:

FAIL  src\actions\__tests__\portletActions.tests.js                                                                                                                      
  ● async actions › calls request and success actions if the fetch response was successful                                                                                

    expect(object).toContain(value)                                                                                                                                       

    Expected object:                                                                                                                                                      
      {"portlets": [// here an array of objects], "type": "LOAD_PORTLETS_SUCCESS"}                                                            
    To contain value:                                                                                                                                                     
      {"type": "LOAD_PORTLETS_SUCCESS"}                                                                                                                                   

      at store.dispatch.then (src/actions/__tests__/portletActions.tests.js:56:34)
      at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:188:7)

在此示例的redux文档中( https://redux.js.org/recipes /writing-tests ),它们收到的结果仅包含执行的操作类型,但我得到的是真实数据和数组内部的操作.

In the redux docs for this example (https://redux.js.org/recipes/writing-tests), they receive a result containing only the action types executed, but I'm getting the real data and the action inside the array.

所以我不确定代码是错误的还是测试是错误的!

So I'm not sure if the code is wrong, or the test, or both!

在此先感谢您的帮助!

推荐答案

您对此单元测试的测试过多.我看到您使用的是thunk,因此您可以更改将获取作为模块传递给thunk的方式,并执行类似的操作.我用过茉莉花,但基本上是一样的东西.您不想仅在此处模拟操作和调度即可模拟您的商店.单元测试的重点应该是测试异步操作,而不是测试从db或redux存储交互中获取真实数据,以便可以将所有内容都存根.

You're testing too much with this unit test. I see you are using thunks it looks like so you can change your fetch to be passed as a module to the thunk and do something like this. I used jasmine but it's basically the same thing. You don't want to mock your store here just the action and dispatch. The point of the unit test should be to test the async action, not to test getting real data from the db or redux store interactions so you can stub all that out.

configureStore看起来像这样...

For reference configureStore would look like this...

const createStoreWithMiddleware = compose(
  applyMiddleware(thunk.withExtraArgument({ personApi }))
)(createStore);

还有测试用例...

  it('dispatches an action when receiving', done => {
    const person = [{ firstName: 'Francois' }];
    const expectedAction = {
      type: ActionTypes.RECEIVED,
      payload: {
        people,
      },
    };

    const dispatch = jasmine.createSpy();
    const promise = Q.resolve(person);
    const personApi = {
      fetchPerson: jasmine
        .createSpy()
        .and.returnValue(promise),
    };

    const thunk = requestPerson();
    thunk(dispatch, undefined, { personApi });

    promise.then(() => {
      expect(dispatch.calls.count()).toBe(2);
      expect(dispatch.calls.mostRecent().args[0]).toEqual(expectedAction);
      done();
    });
  });

这篇关于在React/Redux应用程序中测试提取操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆