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

如何用Sinon对instanceof进行Spy?测试验证遇阻求助

如何用Sinon监视instanceof的调用

直接监视instanceof运算符本身是行不通的,因为它是JavaScript的原生运算符,不是可被Spy的函数。不过我们可以利用ES6引入的Symbol.hasInstance特性,或者通过封装函数的方式来间接实现检测。下面是两种可行的方案:

方案1:利用Symbol.hasInstance(ES6+)

从ES6开始,instanceof的行为会调用目标构造函数的Symbol.hasInstance方法(默认实现就是检查原型链)。我们可以对这个方法进行Spy,从而检测instanceof是否被调用。

示例代码:

const sinon = require('sinon');

// 假设我们要监视的构造函数是MyClass
const MyClass = function() {};

// 1. 保存原始的hasInstance方法
const originalHasInstance = MyClass[Symbol.hasInstance];

// 2. 创建Spy并替换原方法
const hasInstanceSpy = sinon.spy(function(obj) {
  // 调用原始逻辑保证功能正常
  return originalHasInstance.call(this, obj);
});
MyClass[Symbol.hasInstance] = hasInstanceSpy;

// 3. 执行你的被测代码(比如某个会用到obj instanceof MyClass的函数)
function underTest(obj) {
  return obj instanceof MyClass;
}
underTest(new MyClass());

// 4. 断言Spy被调用
sinon.assert.calledOnce(hasInstanceSpy);
// 还可以断言调用参数
sinon.assert.calledWith(hasInstanceSpy, sinon.match.instanceOf(MyClass));

// 5. 恢复原始方法,避免影响其他测试
MyClass[Symbol.hasInstance] = originalHasInstance;

如果你的环境支持sinon.stub的wrap方法,还可以更简洁地实现:

const hasInstanceStub = sinon.stub(MyClass, Symbol.hasInstance).callsFake(function(obj) {
  return MyClass[Symbol.hasInstance].wrappedMethod.call(this, obj);
});

// 执行测试...

sinon.assert.called(hasInstanceStub);
hasInstanceStub.restore();

方案2:封装instanceof调用(兼容旧环境)

如果你的运行环境不支持ES6的Symbol.hasInstance,或者需要监视内置对象(比如Array、Object)的instanceof调用(这类对象的Symbol.hasInstance通常是不可修改的),可以把代码中的instanceof调用封装成一个工具函数,然后Spy这个函数。

示例代码:

// 第一步:在业务代码中封装instanceof检查
function isInstanceOf(obj, constructor) {
  return obj instanceof constructor;
}

// 第二步:在测试中Spy这个封装函数
const sinon = require('sinon');
const isInstanceOfSpy = sinon.spy(isInstanceOf);

// 确保被测代码调用的是这个封装函数,而非直接使用instanceof
function underTest(obj) {
  return isInstanceOfSpy(obj, Array);
}
underTest([1,2,3]);

// 第三步:断言Spy被调用
sinon.assert.calledOnce(isInstanceOfSpy);
sinon.assert.calledWith(isInstanceOfSpy, [1,2,3], Array);

注意事项

  • 对于内置构造函数(如Array、String),修改它们的Symbol.hasInstance可能会失败(因为这些属性通常是不可写/不可配置的),此时方案2会更可靠。
  • 无论用哪种方案,测试完成后记得恢复原始方法/函数,避免污染其他测试用例的环境。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:56:49