我正在进行减速器测试。但是具有动作功能的减速器的返回状态是异常的。
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,
],
}
我必须误解触发减速器功能的用法。我希望得到一些正确的方法来触发减速器的动作并获得预期的结果。
答案 0 :(得分:3)
罪魁祸首可以在你的减速器中找到,特别是这些线:
state.id = status.id + 1;
这里的reducer既改变状态又返回一个新的状态。改变状态是不好的做法,并且可能导致奇怪的效果(就像你正在经历的那样)
所以'2。添加一次'测试会将id增加到0.这将在下一次测试期间保留在内存中,其中 initialStatus 的id为0,而不是-1。在我们的reducer中, state 指向 initialStatus 。所以调用case "ADD": {
const newId = state.id + 1;
return {
id: newId,
list: state.list.concat([newId])
};
}
会增加 initialStatus 的id字段,并且列表相同。这就是看起来ADD动作被调用三次的原因。
远离减速器中的突变可以帮助解决这个问题。
{{1}}
记住,永远不要在reducer中改变状态,总是返回新的状态! (http://redux.js.org/docs/Troubleshooting.html#never-mutate-reducer-arguments)