React中如何Mock地理定位API自定义Hook以完成测试?
如何正确Mock地理定位API测试自定义Hook
你的自定义Hook通过navigator.geolocation获取位置并更新状态,但当前的Mock未触发回调导致测试无法验证状态变化。以下是符合最佳实践的Mock方案,覆盖你需要的三个测试目标:
一、完善地理定位API的Mock逻辑
基础Mock框架可以保留,但需要让getCurrentPosition主动调用传入的成功/错误回调,以此触发Hook内的setCoords。
1. 模拟成功定位场景
通过mockImplementation让Mock调用成功回调,传入模拟的位置数据,验证状态是否正确更新:
import { renderHook } from '@testing-library/react-hooks'; import useGeoLocAPI from './useGeoLocAPI'; const mockPosition = { coords: { latitude: 40.7128, longitude: -74.0060 } }; beforeEach(() => { global.navigator.geolocation.getCurrentPosition.mockClear(); }); test('成功获取位置时,状态被正确设置', () => { global.navigator.geolocation.getCurrentPosition.mockImplementation((success) => { success(mockPosition); }); const { result } = renderHook(() => useGeoLocAPI()); // 断言状态值与结构 expect(result.current[0]).toEqual({ lat: mockPosition.coords.latitude, long: mockPosition.coords.longitude }); // 断言API被调用 expect(global.navigator.geolocation.getCurrentPosition).toHaveBeenCalled(); });
2. 模拟定位失败场景
触发错误回调,验证错误处理逻辑是否生效:
test('定位失败时,错误信息被正确打印', () => { const mockError = { message: '用户拒绝定位权限' }; const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); global.navigator.geolocation.getCurrentPosition.mockImplementation((_, error) => { error(mockError); }); const { result } = renderHook(() => useGeoLocAPI()); // 断言错误处理执行 expect(consoleErrorSpy).toHaveBeenCalledWith(mockError.message); // 断言状态保持初始值 expect(result.current[0]).toBeNull(); consoleErrorSpy.mockRestore(); });
二、验证状态结构
单独测试初始状态和成功后的状态结构:
test('初始状态为null', () => { global.navigator.geolocation.getCurrentPosition.mockImplementation(() => {}); const { result } = renderHook(() => useGeoLocAPI()); expect(result.current[0]).toBeNull(); }); test('成功获取位置后,状态包含lat和long数字类型字段', () => { global.navigator.geolocation.getCurrentPosition.mockImplementation((success) => { success({ coords: { latitude: 1, longitude: 2 } }); }); const { result } = renderHook(() => useGeoLocAPI()); expect(result.current[0]).toHaveProperty('lat'); expect(result.current[0]).toHaveProperty('long'); expect(typeof result.current[0].lat).toBe('number'); expect(typeof result.current[0].long).toBe('number'); });
关键注意事项
- 需安装
@testing-library/react-hooks依赖,用于测试自定义Hook的状态变化。 - 每次测试前重置Mock,避免用例间的状态污染。
- 不要直接Mock
setState,通过触发真实业务逻辑(如地理定位回调)驱动状态更新,这是符合测试最佳实践的方式。
内容的提问来源于stack exchange,提问作者mdwiltfong
相关产品推荐
相关产品推荐

