You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jest测试Google Maps服务函数失败:Mock未生效问题修复

问题:Jest Mock Google Maps Client 未生效,返回结果为 undefined

我有一个 map.service 文件,通过 @googlemaps/google-maps-services-js 的 Client 实例实现了 getGeocodeResult 函数。用 Jest 为该函数写测试时,Mock 始终不生效,返回的 result 一直是 undefined,附上服务代码和测试代码,求解决方法?

服务代码

import { Client } from '@googlemaps/google-maps-services-js';
import logger from '@common/utils/logger';

interface TimezoneObj {
  timezone: string;
  timezoneName: string;
}

// 顶层实例化 Google Maps 客户端
const client = new Client({});

export const getGeocodeResult = async (address: string) => {
  const fN = 'getGeocodeResult';
  logger.info(`${fN} - Getting geo code data for address: ${address}`);
  
  const result = await client.geocode({
    params: {
      address,
      key: process.env.GOOGLE_MAPS_API || ''
    }
  });
  console.log(result);

  return result.data.results[0];
};

测试代码

import { mockGeocodeResponse } from '@mocks/google-maps';
import * as mapService from './map.service';
import { Client, GeocodeResponse } from '@googlemaps/google-maps-services-js';

jest.mock('@googlemaps/google-maps-services-js');

describe('Map Service', () => {
  let client: Client;

  beforeEach(() => {
    client = new Client({}) as jest.Mocked<Client>;

    jest.clearAllMocks();
  });

  describe('getGeocodeResult', () => {
    it.only('should use the API key from the environment variable', async () => {
      process.env.GOOGLE_MAPS_API = 'test-api-key';

      jest.spyOn(client, 'geocode').mockResolvedValueOnce(mockGeocodeResponse);

      const result = await mapService.getGeocodeResult('123 Test St, Test City, TX');

      expect(client.geocode).toHaveBeenCalledWith({
        params: {
          address: '123 Test St, Test City, TX',
          key: 'test-api-key'
        }
      });
      expect(result.formatted_address).toBe('Test Address');
    });
  });
});

问题原因及解决方法

核心问题

测试里新建的 client 实例和服务文件顶层创建的 client 实例不是同一个对象,因此对测试实例的 Mock 不会作用到服务中实际调用的实例上,导致返回 undefined。

修复步骤

  1. 直接 Mock Client 类的原型方法
    无需在测试中新建 Client 实例,而是针对 @googlemaps/google-maps-services-js 导出的 Client 类的原型方法做 Mock,这样服务里的顶层实例会继承这个 Mock 后的方法。

  2. 调整后的测试代码

import { mockGeocodeResponse } from '@mocks/google-maps';
import * as mapService from './map.service';
import { Client } from '@googlemaps/google-maps-services-js';

// 自动 Mock 整个谷歌地图服务模块
jest.mock('@googlemaps/google-maps-services-js');

// 类型断言,让 TypeScript 识别 Mock 后的类类型
const MockClient = Client as jest.MockedClass<typeof Client>;

describe('Map Service', () => {
  beforeEach(() => {
    // 重置所有 Mock 状态
    MockClient.mockClear();
    MockClient.prototype.geocode.mockClear();
  });

  describe('getGeocodeResult', () => {
    it.only('should use the API key from the environment variable', async () => {
      process.env.GOOGLE_MAPS_API = 'test-api-key';

      // 给 geocode 方法设置预设的 Mock 返回值
      MockClient.prototype.geocode.mockResolvedValueOnce(mockGeocodeResponse);

      const result = await mapService.getGeocodeResult('123 Test St, Test City, TX');

      // 验证 Client 类被实例化过
      expect(MockClient).toHaveBeenCalledTimes(1);
      // 验证 geocode 方法的调用参数是否符合预期
      expect(MockClient.prototype.geocode).toHaveBeenCalledWith({
        params: {
          address: '123 Test St, Test City, TX',
          key: 'test-api-key'
        }
      });
      // 验证返回结果是否正确
      expect(result.formatted_address).toBe('Test Address');
    });
  });
});

关键说明

  • jest.mock('@googlemaps/google-maps-services-js') 会自动生成模块的 Mock 版本,包含 Client 类的 Mock 实现。
  • 通过类型断言 jest.MockedClass<typeof Client> 可以避免 TypeScript 类型报错,方便操作 Mock 方法。
  • 服务中的顶层 client 实例基于 Mock 后的 Client 类创建,因此它的 geocode 方法会使用你设置的 Mock 逻辑,返回预设的响应数据。

内容的提问来源于stack exchange,提问作者Attiq Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:55:08