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

单例类的实例方法是否为单例?测试用例失败原因咨询

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 17:17:33