如何使用reactjs和redux动作通过玩笑来测试reducer

时间:2018-08-03 09:47:43

标签: react-redux jestjs

我正在尝试测试减速器,但不确定如何进行。这些教程与代码的外观不同,因此不确定如何实现。

actions / audit.js

   import axios from 'axios';

    export const FETCH_SOX_APPROVED_COMMS = 'fetch_sox_approved_comms';

    export async function fetchSoxApprovedComms(page, size, where, sort) {
        const request = await axios.get(`/api/user/report/sox/approved/comms/format/json?quiet=1&page=` + page + `&size=` + size + `&where=` + JSON.stringify(where) + `&sort=` + sort);
        return {
            type: FETCH_SOX_APPROVED_COMMS,
            payload: request
        };
    }

    export const FETCH_SOX_APPROVED_COMMS_COUNT = 'fetch_sox_approved_comms_count';

    export async function fetchSoxApprovedCommsCount(where) {
        const request = await axios.get(`/api/user/report/sox/approved/comms/count/format/json?quiet=1&where=` + JSON.stringify(where));
        return {
            type: F

ETCH_SOX_APPROVED_COMMS_COUNT,
        payload: request
    };
}

reducers / reducer_audit.js

import { 
    FETCH_SOX_APPROVED_COMMS, 
    FETCH_SOX_APPROVED_COMMS_COUNT
} from '../actions/audit';

export default function(state = {}, action) {
    switch (action.type) {
    case FETCH_SOX_APPROVED_COMMS:
    case FETCH_SOX_APPROVED_COMMS_COUNT:
        if ( typeof action.payload.data !== 'object'){
            return Object.assign({}, state, {
                error: {
                    code: "AUTHENTICATION",
                    message: 'Your session has expired',
                    action
                }
             });
        }else if (action.payload.data.header.error) {
            return Object.assign({}, state, {
                error: {
                    code: "INVALID ACTION",
                    message: action.payload.data.header.message,
                    action
                }
             });

       } else {
           return action.payload.data.body.recordset.record;
       }
    default:
        return state;
    }
}

tests / jest / reducers / reducer_audit.test.js

import reducer from '../../../app/reducers/reducer_audit';
import * as actions from '../../../app/actions/audit';
import expect from 'expect';

describe('audit reducer', () => {
  it('should return the initial state', () => {
    expect(reducer(undefined, {})).toEqual({});
  });

  it('should handle FETCH_SOX_APPROVED_COMMS_COUNT', () => {
      const expected = {
          type: actions.FETCH_SOX_APPROVED_COMMS_COUNT
        };
    // it's empty on purpose because it's just starting to fetch posts
    expect(reducer({}, expected)).toEqual({});
  });

  it('should handle FETCH_SOX_APPROVED_COMMS');
});

我收到的错误是

 audit reducer
    ✓ should return the initial state (2ms)
    ✕ should handle FETCH_SOX_APPROVED_COMMS_COUNT (7ms)
    ○ skipped 1 test

  ● audit reducer › should handle FETCH_SOX_APPROVED_COMMS_COUNT

    TypeError: Cannot read property 'data' of undefined

       8 |      case FETCH_SOX_APPROVED_COMMS:
       9 |      case FETCH_SOX_APPROVED_COMMS_COUNT:
    > 10 |              if ( typeof action.payload.data !== 'object'){
      11 |                      return Object.assign({}, state, {
      12 |                 error: {
      13 |                     code: "AUTHENTICATION",

      at Object.<anonymous>.exports.default (app/reducers/reducer_audit.js:10:30)
      at Object.<anonymous> (tests/jest/reducer/reducer_audit.test.js:15:9)

我已尝试遵循本教程https://medium.com/@netxm/testing-redux-reducers-with-jest-6653abbfe3e1

在我的动作类中,需要执行以下操作,因为我的应用通过SSO,并且如果用户没有经过身份验证的会话,它将返回一个html页面

if ( typeof action.payload.data !== 'object'){
            return Object.assign({}, state, {
                error: {
                    code: "AUTHENTICATION",
                    message: 'Your session has expired',
                    action
                }
             });
        }

更新

我添加了一些预期的动作,但是如果我指定要接收的数据并匹配输出,我将无法理解它的工作原理。

    import reducer from '../../../app/reducers/reducer_audit';
    import * as actions from '../../../app/actions/audit';
    import expect from 'expect';

    describe('audit reducer', () => {
      it('should return the initial state', () => {
        expect(reducer(undefined, {})).toEqual({});
      });

      it('should handle FETCH_SOX_APPROVED_COMMS_COUNT', () => {
          const expected = {
                    id: 1,
                    name: 'testname'
                  };

          let action = {
                  type: actions.FETCH_SOX_APPROVED_COMMS_COUNT,
                  payload: {
                    data: {
                      header: {
                        error: null
                      },
                      body: {
                        recordset: {
                          record: {
                            id: 1,
                            name: 'testname'
                          }
                        }
                      }
                    }
                  }
                }
        expect(reducer({}, action)).toEqual(expected);
      });

      it('should handle FETCH_SOX_APPROVED_COMMS', () => {
          const expected = {
                  'approver_email':'',
                  'id':1,
                  'sox_approved':'',
                  'sox_submission':'',
                  'submitted_by':''
                  };

          let action = {
                  type: actions.FETCH_SOX_APPROVED_COMMS,
                  payload: {
                    data: {
                      header: {
                        error: null
                      },
                  body: {
                    recordset: {
                      record: {
                          'approver_email':'',
                          'id':1,
                          'sox_approved':'',
                          'sox_submission':'',
                          'submitted_by':''
                      }
                    }
                  }
                }
              }
            }
    expect(reducer({}, action)).toEqual(expected);
  });
});

如果我手动通过action结果,然后手动通过expected,该如何测试?我知道我需要手动传递expected,但是我不明白为什么我也必须将结果集输入action中。我本以为我的action.fetchSoxApprovedCommsCount必须提供参数并期望expected?是否需要导入肌动蛋白文件?

我在https://codesandbox.io/s/olwyjrwnjz

处添加了最少的代码

1 个答案:

答案 0 :(得分:1)

收到错误消息是因为忘记了在测试操作中包含有效载荷。

您要将以下操作传递给减速器。

{
  type: actions.FETCH_SOX_APPROVED_COMMS_COUNT
}

Reducer尝试读取action.payload.data,这会导致错误,因为action.payloadundefined

您必须传递带有一些实际数据的动作。例如:

const action = {
  type: actions.FETCH_SOX_APPROVED_COMMS_COUNT,
  payload: {
    data: {
      header: {
        error: null
      },
      body: {
        recordset: {
          record: {
            id: 1,
            name: 'testname'
          }
        }
      }
    }
  }
}

之后,您应该expect适当的值。在我的例子中

expect(reducer({}, action)).toEqual({ id: 1, name: 'testname' })

会通过。