Jest测试报TypeError: subscribe is not a function问题排查
问题产生原因
报错的核心原因是Observable类构造函数的错误返回逻辑:
constructor(emitter){ return this._emitter = emitter }
JavaScript中new操作符调用构造函数时遵循以下规则:
- 如果构造函数显式
return的值是对象类型(函数、普通对象、数组等都属于对象),new表达式最终返回这个自定义的返回值,而非类的实例对象this - 如果构造函数显式
return的值是原始类型(undefined、null、数字、字符串、布尔值),该返回值会被忽略,默认返回类实例this
两个测试用例表现不一致的原因也来源于此:
- 第一个测试
new Observable()没有传入参数,emitter为undefined(原始类型),构造函数的return语句被忽略,返回的是真正的Observable类实例,因此可以正常调用实例方法foo(),测试通过。 - 第二个测试传入了一个箭头函数作为
emitter参数,函数属于对象类型,因此构造函数直接把这个传入的箭头函数作为new的返回值。最终fakeAsyncData$拿到的是你传入的回调函数,根本不是Observable的实例,自然不存在subscribe方法,触发类型错误。
修复方案
- 首先修正构造函数逻辑,去掉return语句,仅将传入的emitter挂载到实例属性上即可:
constructor(emitter){ this._emitter = emitter }
- 附带修正
subscribe方法的潜在问题:原代码中error、complete参数的默认值是空对象,后续调用时会触发类型错误,应改为默认空函数;同时统一参数处理逻辑,兼容「传入单个observer对象」和「依次传入next/error/complete回调」两种调用方式。
修复后的完整Observable代码如下:
export class Observable { constructor(emitter){ this._emitter = emitter } foo(){ return 'bar' } subscribe(observerOrNext, error = () => {}, complete = () => {}){ const observer = typeof observerOrNext === "function" ? { next: observerOrNext, error, complete } : observerOrNext return this._emitter(observer) } }
修改后重新运行测试,两个用例均可正常通过。
内容的提问来源于stack exchange,提问作者Tyler B. Joudrey
相关产品推荐
相关产品推荐

