如何在Jest中测试window.scrollY相关代码并满足测试覆盖率要求?
测试前准备
确保测试环境已安装jest和@testing-library/react(或其他React测试相关依赖),我们需要模拟window对象、setScrollUp和setLastScrollY状态更新函数,以及lastScrollY变量。
测试用例编写
import { renderHook, act } from '@testing-library/react'; // 封装待测试逻辑,便于传入依赖项 const setupControlNavbar = (lastScrollY, setScrollUp, setLastScrollY) => { const controlNavbar = () => { if (typeof window !== 'undefined') { if (window.scrollY > lastScrollY) { setScrollUp(false); } if (window.scrollY < lastScrollY) { setScrollUp(true); } setLastScrollY(window.scrollY); } }; return controlNavbar; }; describe('controlNavbar function', () => { let originalWindow; // 测试前保存原始window对象,测试后恢复 beforeEach(() => { originalWindow = global.window; global.window = { scrollY: 0 }; }); afterEach(() => { global.window = originalWindow; }); it('window未定义时不执行任何操作', () => { global.window = undefined; const mockSetScrollUp = jest.fn(); const mockSetLastScrollY = jest.fn(); const controlNavbar = setupControlNavbar(100, mockSetScrollUp, mockSetLastScrollY); controlNavbar(); expect(mockSetScrollUp).not.toHaveBeenCalled(); expect(mockSetLastScrollY).not.toHaveBeenCalled(); }); it('scrollY大于lastScrollY时,设置scrollUp为false并更新lastScrollY', () => { global.window.scrollY = 200; const mockSetScrollUp = jest.fn(); const mockSetLastScrollY = jest.fn(); const controlNavbar = setupControlNavbar(100, mockSetScrollUp, mockSetLastScrollY); act(() => { controlNavbar(); }); expect(mockSetScrollUp).toHaveBeenCalledWith(false); expect(mockSetLastScrollY).toHaveBeenCalledWith(200); }); it('scrollY小于lastScrollY时,设置scrollUp为true并更新lastScrollY', () => { global.window.scrollY = 50; const mockSetScrollUp = jest.fn(); const mockSetLastScrollY = jest.fn(); const controlNavbar = setupControlNavbar(100, mockSetScrollUp, mockSetLastScrollY); act(() => { controlNavbar(); }); expect(mockSetScrollUp).toHaveBeenCalledWith(true); expect(mockSetLastScrollY).toHaveBeenCalledWith(50); }); it('scrollY等于lastScrollY时,不修改scrollUp但更新lastScrollY', () => { global.window.scrollY = 100; const mockSetScrollUp = jest.fn(); const mockSetLastScrollY = jest.fn(); const controlNavbar = setupControlNavbar(100, mockSetScrollUp, mockSetLastScrollY); act(() => { controlNavbar(); }); expect(mockSetScrollUp).not.toHaveBeenCalled(); expect(mockSetLastScrollY).toHaveBeenCalledWith(100); }); });
关键说明
- 用
beforeEach和afterEach维护window对象的纯净性,避免测试用例间互相干扰 - 用
jest.fn()模拟状态更新函数,方便断言调用情况和参数 - 用
act()包裹函数调用,确保React状态更新的副作用被正确捕获 - 覆盖了所有分支场景:window不存在、scrollY大于/小于/等于lastScrollY
内容的提问来源于stack exchange,提问作者Shamaz saeed
相关产品推荐
相关产品推荐

