升级uuid至v9后,如何使用Sinon stub uuid v4方法?
如何在uuid v9.0.0中用Sinon Stub v4方法?
问题背景
我将NodeJS及依赖版本更新后,尝试把uuid从v3.1.0升级到v9.0.0,测试中原先可用的Sinon Stub代码失效了。原代码如下:
sinon = require('sinon'), uuid = require('uuid'), before(async () => { uuidV4Stub = sinon.stub(uuid, 'v4').returns('RANDOM_ID'); });
查阅uuid的npm文档后发现,从uuid@7版本开始提供ECMAScript模块构建,支持Webpack、Rollup等打包工具的摇树优化,且移除了默认导出,需使用如下引入方式:
ES模块语法:
import { v4 as uuidv4 } from 'uuid'; uuidv4();
CommonJS语法:
const { v4: uuidv4 } = require('uuid'); uuidv4();
想问现在是否仍可以对uuid v4方法进行Stub?
解决方案
当然可以对uuid v4方法进行Stub,只是需要根据新的引入规则调整写法:
1. CommonJS环境下的写法
如果项目使用CommonJS语法,不要直接解构v4方法,保留对uuid模块的完整引用,这样就能正常Stub:
const sinon = require('sinon'); const uuid = require('uuid'); // 保留完整模块引用,不解构 before(async () => { uuidV4Stub = sinon.stub(uuid, 'v4').returns('RANDOM_ID'); }); // 业务代码中需使用uuid.v4(),而非解构后的局部变量
如果业务代码里用了解构写法(const { v4: uuidv4 } = require('uuid')),需要修改业务代码为从完整模块上调用v4,否则Stub不会生效——因为解构会把v4的引用复制到局部变量,Stub的是模块上的方法,无法影响局部变量的引用。
2. ES模块环境下的写法
ES模块的导出是只读的,无法直接修改,需要借助模块拦截工具来Stub,比如esmock(专门适配ES模块)或proxyquire(兼容CommonJS):
用esmock实现:
import sinon from 'sinon'; import esmock from 'esmock'; before(async () => { // 拦截uuid模块,替换v4为Stub const uuid = await esmock('uuid', { v4: sinon.stub().returns('RANDOM_ID') }); // 确保业务代码引入的是被拦截后的uuid模块 });
用proxyquire实现:
const sinon = require('sinon'); const proxyquire = require('proxyquire'); before(async () => { const uuidStub = { v4: sinon.stub().returns('RANDOM_ID') }; // 用proxyquire加载业务代码,替换其中的uuid模块为Stub const yourModule = proxyquire('./your-module.js', { 'uuid': uuidStub }); });
关键注意事项
- 避免直接解构
v4方法后再Stub,解构会生成方法副本,Stub模块上的方法无法影响副本。 - ES模块环境必须使用模块拦截工具,因为ES模块导出不允许直接修改。
内容的提问来源于stack exchange,提问作者PlayHardGoPro
相关产品推荐
相关产品推荐

