ReactJS:如何在 Jest 中通过动作触发减速器

Posted

技术标签:

【中文标题】ReactJS:如何在 Jest 中通过动作触发减速器【英文标题】:ReactJS: how to trigger reducer with action in Jest 【发布时间】:2017-09-26 01:36:22 【问题描述】:

我正在进行减速器测试。但是带有action函数的reducer返回状态异常。

reducer.react-test.js

import reducer from '../../test_module/reducer';

describe('Test Reducer', () => 

  const initStatus =  id: -1, list: [] ;

  it('1. has default state', () =>     
    expect(reducer(initStatus,  type: 'unexpected' )).toEqual(
      ...initStatus
    );    
  );

  it('2. has added once', () =>     
    expect(reducer(initStatus,  type: "ADD" )).toEqual(
      ...initStatus,
      id: 0,
      list: [0],
    );   
  );

  it('3. has added twice', () =>     
    const afterAddOnce = reducer(initStatus,  type: "ADD" );
    expect(reducer(afterAddOnce,  type: "ADD" )).toEqual(
      ...initStatus,
      id: 1,
      list: [0,1],
    );    
  );
)

reducer.js

export default function reducer(state=
    id: -1, list: [],
  , action) 
  switch(action.type) 

    case "ADD": 
      state.id = state.id + 1;
      state.list.push(state.id);
      return 
        ...state,
      ;
    
  
  return state;

文件夹结构

.
├── __test__
│   └── test_module
│       └── reducer.react-test.js
└── test_module
    └── reducer.js

我的第一个和第二个测试用例按预期工作。

但是,当我尝试触发动作两次时,我存储了第一个动作的返回状态。但是返回状态是意外的,它执行了两次ADD动作。 (我预计只有一次)

因此我在运行 jest 时得到了这个结果:

FAIL  __test__/test_module/reducer.react-test.js
  ● Test Reducer › has added twice

    expect(received).toEqual(expected)

    Expected value to equal:
      "id": 1, "list": [0, 1]
    Received:
      "id": 2, "list": [0, 1, 2]

    Difference:

    - Expected
    + Received

     Object 
    -  "id": 1,
    +  "id": 2,
       "list": Array [
         0,
         1,
    +    2,
       ],
     

我一定误解了用action触发reducer函数的用法。我希望能找到一些正确的方法来触发减速器并获得预期的结果。

【问题讨论】:

【参考方案1】:

罪魁祸首可以在你的减速器中找到,特别是这些行:

state.id = state.id + 1;
state.list.push(state.id);

这里的 reducer 既改变了状态,又返回了一个新的状态。改变状态是不好的做法,并且会导致奇怪的效果(就像你正在经历的那样)

所以 '2.已添加一次' 测试会将 id 增加到 0。这将在下一次测试期间保留在内存中,其中 initialStatus 的 id 将为 0,而不是 -1。在我们的 reducer 中,state 指向 initialStatus。所以调用state.id = status.id + 1; 会增加initialStatus 的id 字段,列表也是如此。这就是为什么 ADD 操作似乎被调用了 3 次的原因。

远离减速器中的突变可以帮助解决这个问题。

case "ADD": 
    const newId = state.id + 1;

    return 
      id: newId,
      list: state.list.concat([newId])
    ;

记住,永远不要在 reducer 中改变状态,总是返回新的状态! (http://redux.js.org/docs/Troubleshooting.html#never-mutate-reducer-arguments)

【讨论】:

以上是关于ReactJS:如何在 Jest 中通过动作触发减速器的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Xcode 中通过代码触发按钮

如何在 Reactjs 中通过 websocket 使用 MQTT?

如何使用 Jest 测试 Reflux 动作

react+redux 中如何通过请求动作处理中间件并触发成功动作?

Axios 基本授权未在 Reactjs 中通过

如何在功能性 React JS 组件中获取数据?