Jest+Enzyme单元测试onChange触发但日期字段值未更新问题
问题原因
你遇到的问题本质是对受控组件的测试逻辑和Enzyme渲染机制理解有偏差,具体有三点核心错误:
- 你mock的
onChangeDateRange仅做了调用监听,没有实现状态更新逻辑。被测Date组件是纯受控组件,自身不存储日期状态,所有日期值都来自父组件传入的props:真实运行时,onChangeDateRange触发后父组件会更新自身state,再把新的startDate、endDate回传给Date组件触发重渲染。但测试里的jest.fn()只是个空函数,只会记录被调用的情况,根本不会修改传入组件的props,组件自然永远只能拿到初始值。 - 你在触发点击事件前就提前缓存了
DateRangeCalendar的节点引用。Enzyme的shallow渲染返回的是渲染时刻的节点快照,就算后续组件重渲染,你提前存的这个变量还是指向第一次渲染生成的旧节点,读出来的props必然是初始值。 - 额外的逻辑错误:组件里
previousRange、nextRange方法传给onChangeDateRange的是moment对象,不是你断言里写的字符串格式,就算props更新了,直接和字符串做相等判断也会失败。
修正方案
这个组件的核心职责是点击按钮时计算出正确的新日期范围,通过回调抛给父组件,不需要在这个组件的单测里模拟父组件的完整更新链路,直接断言mock函数的入参符合预期即可。如果需要验证props传入新值后的渲染效果,手动调用setProps触发重渲染,且重渲染后要重新查找子节点,不要用旧的缓存引用。
修正后的上一页按钮测试用例参考:
it('should call onChangeDateRange when clicking previousButton ', () => { // 清空之前用例的mock调用记录,避免干扰 onChangeDateRange.mockClear() wrapper = shallow( <Date onChangeDateRange={onChangeDateRange} startDate='2022-3-28' endDate='2022-3-29' /> ) wrapper.find('Button').at(0).simulate('click') expect(onChangeDateRange).toHaveBeenCalledTimes(1) // 校验回调传入的参数计算正确 const [callArg] = onChangeDateRange.mock.calls[0] expect(callArg.startDate.format('YYYY-M-D')).toEqual('2022-3-26') expect(callArg.endDate.format('YYYY-M-D')).toEqual('2022-3-27') // 若要验证新props传入后的渲染,手动更新props wrapper.setProps({ startDate: '2022-3-26', endDate: '2022-3-27' }) // 重渲染后重新查找节点,不要用之前缓存的引用 const updatedCalendar = wrapper.find('DateRangeCalendar') expect(updatedCalendar.props().startDate).toEqual('2022-3-26') expect(updatedCalendar.props().endDate).toEqual('2022-3-27') })
下一页按钮的测试用例按照同样逻辑修改即可。
内容的提问来源于stack exchange,提问作者Jessie L
相关产品推荐
相关产品推荐

