单例类的实例方法是否为单例?测试用例失败原因咨询
TypeScript单例类疑问与测试问题解析
你实现的TypeScript单例类ABC代码如下:
class ABC { private static instance: ABC private constructor() {} //This is only for unit-testing static reset() { this.instance = null } public static getInstance(): ABC { if (!this.instance) { this.instance = new ABC() } return ABC.instance } public async getData(params): Promise<string> { switch (someCondition()) { case A: case B: case C: return await this.method1(someParam) case D: return this.method2() case E: try { return this.anotherMethod() } catch (err) { throw err } } } }
对应的单元测试代码:
describe("ABC should be singleton", () => { it("should return the same instance of ABC", async () => { expect(ABC.getInstance()).toBe(ABC.getInstance()) }) it("should not return the same instance of ABC in case the it is null", async () => { const instance1 = await ABC.getInstance() //resetting the value ABC.reset() const instance2 = await ABC.getInstance() expect(instance1).not.toBe(instance2) }) it("should return the same instance of ABC in case getCredential is called with the same parameters", async () => { const instance1 = await ABC.getInstance().getData({}, { param1, param2 }) const instance2 = await ABC.getInstance().getData({}, { param1, param2 }) expect(instance1).toBe(instance2) }) })
前两个测试通过,但第三个测试失败,针对你的两个疑问解答如下:
疑问1:单例类的实例方法是否也属于单例?
单例的核心是类的实例唯一,实例方法是挂载在类的原型上的,所有该类的实例(这里只有一个单例实例)共享同一个方法引用。但你第三个测试的逻辑有误:你在比较的是getData方法的返回值,而非方法本身。
- 若
getData返回Promise,每次调用都会生成新的Promise实例,即便最终resolve的内容相同,toBe(比较引用地址)也会判定不相等; - 若
method1/method2等方法每次返回不同的字符串内容,两次调用getData的返回值自然也不一样。
疑问2:若ABC先以A、B参数调用,再以D、C参数调用,是否会重新初始化实例?
不会。单例的初始化逻辑仅在getInstance中,只有当静态属性instance为null时,才会创建新实例。无论调用单例实例的哪个方法、传入什么参数,只要未调用reset清空instance,getInstance都会返回同一个已创建的实例,不会重新初始化。
第三个测试失败的解决思路
你混淆了“单例实例”和“实例方法的返回值”:
- 若要验证
getData方法本身是同一个引用,可修改测试为:expect(ABC.getInstance().getData).toBe(ABC.getInstance().getData) - 若要验证相同参数下
getData的返回内容一致,应该用toEqual(比较值)代替toBe(比较引用):expect(instance1).toEqual(instance2)
内容的提问来源于stack exchange,提问作者MarioBros
相关产品推荐
相关产品推荐

