
Sinon 的 createStubInstance 不会执行构造函数,因此实例上未初始化的属性(包括构造函数中声明的 public readonly 参数)无法直接被 sinon.stub().value() 存根,需先手动赋值使其存在。
sinon 的 `createstubinstance` 不会执行构造函数,因此实例上未初始化的属性(包括构造函数中声明的 `public readonly` 参数)无法直接被 `sinon.stub().value()` 存根,需先手动赋值使其存在。
在使用 Sinon 进行单元测试时,sinon.createStubInstance(Class) 是一种快速生成“类形似对象”的常用方式——它会为类的所有方法创建 stub,并返回一个空壳实例。但需要注意:该实例不会调用构造函数,因此所有在构造函数中初始化的属性(如 public readonly myParameter: string)根本不会存在于实例上。这正是你遇到 TypeError: Cannot stub non-existent property myParameter 的根本原因。
为什么 myParameter 不存在?
TypeScript 中的 public constructor(public readonly myParameter: string) 实际编译为 JavaScript 后,等价于:
constructor(myParameter) {
this.myParameter = myParameter; // 构造函数内赋值
}而 createStubInstance 绕过了构造函数执行,导致 myClass.myParameter 属性从未被定义,自然无法被 Sinon 存根。
✅ 正确解决方案:先“占位”,再存根
你需要在调用 sinon.stub(...).value(...) 之前,确保目标属性已存在于实例上。由于 TypeScript 对 readonly 属性有严格检查,需通过类型断言绕过编译器限制:
describe("stubs", () => {
it("should pass", () => {
const myClass = sinon.createStubInstance(MyClass);
// 关键步骤:手动设置属性(使属性存在),TS 中需 as any 绕过 readonly 限制
(myClass as any).myParameter = undefined;
// 此时属性已存在,可安全存根
sinon.stub(myClass, "myParameter").value("a");
expect(myClass.myParameter).toBe("a"); // ✅ 通过
});
});? 提示:赋值内容本身不重要(
null、undefined或任意占位值均可),关键是触发属性在myClass原型链上的“存在性”。
? 扩展场景:存根复杂类型属性
当属性是另一个类实例时,同样适用该模式:
// 假设 MyClass 有一个依赖属性
class MyClass {
constructor(public readonly service: SomeService) {}
}
// 测试中:
const myClass = sinon.createStubInstance(MyClass);
(myClass as any).service = null; // 先占位
sinon.stub(myClass, "service").value(sinon.createStubInstance(SomeService));
// 现在可安全访问并验证嵌套行为
expect(myClass.service.doSomething).to.be.a("function");⚠️ 注意事项与最佳实践
-
不要滥用
as any:仅在明确需要绕过 TS 类型系统(如初始化只读属性)时使用,避免掩盖真实类型问题。 -
考虑替代方案:若大量依赖属性存根,可能说明设计耦合度高;优先考虑依赖注入 + 真实实例 +
sinon.replace或sinon.useFakeTimers等更语义化的测试策略。 -
createStubInstance的适用边界:它适合快速模拟“无状态”接口行为;对强依赖构造逻辑或属性初始化的类,建议改用sinon.stub(new MyClass(...))或手动构造 + 方法级 stub。 - Sinon v15+ 变化:新版 Sinon 对属性 stub 支持更严格,此方案在 v14–v17 均有效,无需额外 polyfill。
总之,理解 createStubInstance 的“零初始化”本质,是解决此类问题的关键。先让属性落地,再赋予行为——这是 Sinon 属性 stub 的可靠范式。

















