我最近在我的React应用程序的redux reducer中开始使用Immer,因为其中有很多嵌套状态。 (请避免这样的事实,这些嵌套可以使用sub reducer来解决)。
Immer的用法对我来说很清楚,但是一旦我开玩笑地开始编写单元测试,我就开始感到纳闷,那我应该避免在测试中使用Immer吗?
让我们有一个简单的减速器示例:
export default function (state = initialState, action) {
return produce(state, (draftState) => {
switch (action.type) {
case MY_TYPE:
draftState.some.nested.flag = true;
break;
}
});
}
然后我的测试也使用Immer
it('should handle MY_TYPE', () => {
const storeState = reducer(initialState, {
type: MY_TYPE
});
const newState = produce(initialState, (draftState) => {
draftState.some.nested.flag = true;
});
expect(storeState).toEqual(newState);
});
所以我的问题是,我应该避免在测试中使用Immer产生器,并使用传播语法手动制作嵌套对象的副本吗?像这样:
.toEqual({
...initialState,
some: {
...initialState.some,
nested: {
...initialState.some.nested,
flag: true
}
}
})
那么在测试中使用Immer有什么陷阱吗?
答案 0 :(得分:0)
在这种情况下,Immer不会更改所有状态。例如:
const state = {
some: {
another: {},
nested: {
flag: true
}
}
};
const nextState1 = produce(state, draft => {
draft.some.nested.flag = false;
});
const nextState2 = produce(state, draft => {
draft.some.nested.flag = false;
});
expect(nextState1).toEqual(nextState2);
expect(nextState1.another).toBe(nextState2.another); // true!
expect(nextState1).toBe(nextState2); // false
expect(nextState1.some).toBe(nextState2.some); // false
expect(nextState1.some.nested).toBe(nextState2.some.nested); // false
其中“ toBe”是用于检查对象实例身份的函数(与“ toEqual”不同)。我认为,您不应该避免在单元测试中使用Immer。可能需要另一个assert函数来检查树的仅一部分是否被更改。