JavaScript单元测试模拟第三方SDK全局对象的核心是测试前替换、测试后还原全局变量以避免污染;常用方法包括直接赋值覆盖(推荐Object.defineProperty)、模块级jest.mock()、动态注入清理,需注意不可配置属性、访问时机、环境兼容及this绑定问题。

在 JavaScript 单元测试中模拟第三方 SDK 的全局对象,核心思路是:在测试前临时替换或注入该全局变量,并在测试后还原,避免污染全局环境和其他测试用例。常见于模拟 window.AliyunOSS、window.TencentCloud、window.BaiduMap 等 SDK 提供的全局构造函数或命名空间。
直接赋值覆盖全局对象(适用于简单场景)
如果 SDK 仅挂载在 window(浏览器)或 globalThis(通用)上,且测试运行在 JSDOM 或 Node.js 模拟环境中,可直接赋值模拟:
- 测试前用
Object.defineProperty或直接赋值创建 mock 对象(推荐用defineProperty避免被delete或意外重写) - 测试后通过
afterEach还原原始值(Jest 中可用jest.restoreAllMocks()或手动缓存/恢复) - 示例(Jest):
let originalAliyunOSS;
beforeEach(() => {
originalAliyunOSS = globalThis.AliyunOSS;
globalThis.AliyunOSS = jest.fn().mockImplementation(() => ({
put: jest.fn().mockResolvedValue({}),
get: jest.fn().mockResolvedValue({}),
}));
});
afterEach(() => {
globalThis.AliyunOSS = originalAliyunOSS;
});
使用 Jest 的 jest.mock() + jest.requireActual()(不适用全局挂载,但可用于模块化 SDK)
若第三方 SDK 支持 ESM/CJS 引入(如 import { OSS } from 'ali-oss'),优先用模块级 mock,更安全可控:
- 在测试文件顶部使用
jest.mock('ali-oss'),然后用requireActual保留部分真实行为(可选) - 导出的类或函数可被
jest.fn()替换,无需操作全局对象 - 适合 SDK 已封装为可 import 模块的场景,比操作
window更符合现代工程实践
动态注入 + 清理(适配多环境 & 多 SDK 共存)
当项目同时使用多个全局 SDK(如地图 + 支付 + 存储),需确保互不干扰:
立即学习“Java免费学习笔记(深入)”;
- 用
jest.isolateModules()隔离模块加载(Jest v29+) - 对每个测试用例单独设置全局变量,避免跨 test 泄露
- 使用
jest.resetModules()和jest.clearAllMocks()保证干净状态 - 若 SDK 初始化依赖
document或script标签(如百度地图异步加载),可在 JSDOM 中模拟document.createElement('script')并触发 onload 回调
注意防坑细节
模拟全局 SDK 容易踩的几个关键点:
-
不要用
delete window.XXX:某些全局属性是不可配置的(如window.console),删除会报错;应始终用缓存 + 赋值还原 -
检查访问时机:若代码在模块顶层就访问
window.AliyunOSS,mock 必须在import前生效(Jest 中可用setupFilesAfterEnv或jest.mock的 factory 参数控制) -
区分浏览器与 Node 环境:Node 中无
window,统一用globalThis更健壮 -
模拟原型方法时注意 this 绑定:确保 mock 实例方法能正确访问内部状态(必要时用
jest.fn().mockReturnThis())


















