如何在Jest中测试SectionList的onViewableItemsChanged回调?
解决方案
- 第一步:补全useEffect依赖数组
你当前的useEffect未声明依赖数组,会在组件每次重渲染时重复执行。先调整为仅组件挂载时执行一次的逻辑:
useEffect(() => { sectionListRef.current?.recordInteraction(); }, []);
- 第二步:自定义mock React Native SectionList的逻辑
Jest默认的原生组件mock不会自动触发onViewableItemsChanged回调,也不会实现recordInteraction实例方法,需要手动补全mock逻辑:
jest.mock('react-native', () => { const React = require('react'); const ActualRN = jest.requireActual('react-native'); return { ...ActualRN, SectionList: jest.fn((props) => { // 实现ref暴露的recordInteraction方法 React.useImperativeHandle(props.ref, () => ({ recordInteraction: jest.fn(), })); // 挂载时主动触发onViewableItemsChanged模拟初始可见性变更 React.useEffect(() => { props.onViewableItemsChanged?.({ viewableItems: [ // 按你的业务场景填充模拟的可见分组数据 { section: { id: 'sec1', title: '第一组' }, isViewable: true } ], changed: [] }); }, []); return <ActualRN.SectionList {...props} />; }) }; });
- 第三步:编写覆盖分支的测试用例
分别覆盖ref存在、ref不存在两种分支,同时验证可见性变更后的业务逻辑是否符合预期:
// 覆盖ref存在,recordInteraction被调用,可见性更新逻辑生效的场景 it('should trigger viewable check on mount and update active section', () => { const { getByTestId } = render(<YourCustomSectionList />); // 验证recordInteraction被调用 const sectionListMock = require('react-native').SectionList; expect(sectionListMock).toHaveBeenCalled(); const sectionListInstance = sectionListMock.mock.results[0].value.ref.current; expect(sectionListInstance.recordInteraction).toHaveBeenCalledTimes(1); // 验证激活状态更新符合预期,这里按你实际的渲染逻辑写断言 expect(getByTestId('current-active-section')).toHaveTextContent('第一组'); }); // 覆盖ref为空,可选链不执行的分支 it('should not crash when sectionList ref is not initialized', () => { // 比如传入props控制不渲染SectionList,让ref初始为null render(<YourCustomSectionList hideList={true} />); // 无报错即验证通过 });
内容的提问来源于stack exchange,提问作者Archimedes Trajano
相关产品推荐
相关产品推荐

