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

TypeScript环境下Jest spyOn监听SendGrid send函数失效问题

解决Jest测试SendGrid send函数调用问题(TypeScript环境)

你的问题核心有两个:一是测试环境缺少SendGrid API key导致的Unauthorized错误,二是jest.spyOn没有正确监听send函数的调用。下面是具体的修复方案:

1. 用jest.mock替代spyOn模拟整个SendGrid模块

直接使用jest.spyOn可能因为模块加载顺序问题,无法覆盖到Mutation中导入的sgMail实例。更好的方式是直接模拟整个@sendgrid/mail模块,既能避免真实API调用,也能准确监听函数调用。

修改测试代码如下:

import { gql } from 'graphql-tag';
import { client } from '../your-client-path'; // 替换为你的client实际路径

// 模拟整个@sendgrid/mail模块,替换所有方法为jest mock函数
jest.mock('@sendgrid/mail', () => ({
  setApiKey: jest.fn(), // 模拟API key设置函数,避免真实校验
  send: jest.fn().mockResolvedValue('Success') // 模拟发送函数,返回成功Promise
}));

// 必须在mock之后导入Mutation模块,确保它使用的是模拟版sgMail
import { Mutation } from '../your-mutation-path'; // 替换为你的Mutation文件实际路径

const signUpUserMutation = gql`
  mutation($data: ValidationInput) {
    signUpUser (data: $data) {
      id
      email
    }
  }
`;

it('should send a registration email, with a link containing the registration id', async () => {
  // 从模拟模块中获取send函数的mock实例
  const { send } = require('@sendgrid/mail');
  
  const variables = {
    data: {
      email: "test@test.de",
      password: "anyPassword"
    }
  };

  await client.mutate({ mutation: signUpUserMutation, variables });

  // 断言send函数被调用
  expect(send).toHaveBeenCalled();
  // 还可以进一步校验调用参数是否符合预期
  expect(send).toHaveBeenCalledWith(expect.objectContaining({
    to: "test@test.de",
    subject: "Account validation"
  }));
});

2. 为什么原来的spyOn不生效?

在你的原始代码中,测试文件导入Mutation模块时,Mutation已经加载并执行了sgMail.setApiKey,此时它使用的是真实sgMail实例的引用。之后再用spyOn去监听,无法覆盖这个已经被引用的函数。而jest.mock会在模块加载前替换整个模块,确保Mutation从一开始就使用模拟版本。

3. 解决Unauthorized错误

通过完全模拟@sendgrid/mail模块,真实的setApiKey和send逻辑都不会被执行,自然不会因为缺少API key抛出Unauthorized错误。

额外提示:保留部分真实逻辑的场景

如果你希望保留setApiKey的真实逻辑,只模拟send函数,可以修改mock方式:

jest.mock('@sendgrid/mail', () => {
  const originalModule = jest.requireActual('@sendgrid/mail');
  return {
    ...originalModule,
    send: jest.fn().mockResolvedValue('Success')
  };
});

这种情况下需要在测试环境中设置MAIL_API_KEY(比如通过dotenv加载测试环境变量),否则setApiKey仍可能触发错误,因此更推荐第一种完全模拟的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:56:57