如何测试在useEffect中调用模拟Geolocation的React自定义Hook?
解决方案
首先要确保正确模拟navigator.geolocation.getCurrentPosition,让它能触发回调更新状态,再结合React Testing Library的waitFor等待状态更新完成,就能解决常规测试下无法获取异步结果的问题。
1. 完善模拟逻辑
在测试文件顶部添加全局模拟代码,让getCurrentPosition立即执行成功回调:
beforeAll(() => { const mockGeolocation = { getCurrentPosition: jest.fn((success) => Promise.resolve().then(() => success({ coords: { latitude: 40.7128, longitude: -74.0060, accuracy: 100, altitude: null, altitudeAccuracy: null, heading: null, speed: null, }, }) ) ), }; global.navigator.geolocation = mockGeolocation; }); afterAll(() => { jest.restoreAllMocks(); });
2. 修改测试代码,等待状态更新
setCoords是异步更新状态的操作,直接断言会拿到初始的undefined,用waitFor可以轮询断言直到状态更新完成:
import { renderHook, waitFor } from '@testing-library/react'; import useGeolocation from './useGeolocation'; it('should return non-empty coords', async () => { const { result } = renderHook(() => useGeolocation()); await waitFor(() => { expect(result.current).not.toBeUndefined(); }); // 可额外断言具体坐标值验证正确性 expect(result.current?.latitude).toBe(40.7128); expect(result.current?.longitude).toBe(-74.0060); });
问题原因说明
调试模式下代码执行速度慢,状态更新有足够时间完成;但常规测试运行时代码同步执行,状态还未更新就触发了断言。waitFor会持续检查断言条件,直到满足或超时,刚好适配这种异步状态更新场景。
内容的提问来源于stack exchange,提问作者sKopheK
相关产品推荐
相关产品推荐

