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

如何在Jest中模拟可调用对象?附Kubernetes-Client示例问题

问题:Kubernetes Client Jest 模拟同时支持两种调用方式失败

业务代码中client.api.v1.namespaces存在两种合法调用方式:

  • 作为对象调用:client.api.v1.namespaces.post(namespaceJson)
  • 作为函数调用:client.api.v1.namespaces(namespaceName).get()

但当前Jest模拟代码将namespaces设为函数后,调用post方法时会提示“不是函数”,导致测试失败。

业务代码

console.log(`Trying to create a namespace: ${namespaceName}`)
try {
  await client.api.v1.namespaces(namespaceName).get()
} catch (err) {
  try {
    await client.api.v1.namespaces.post(namespaceJson)
  } catch (err) {
    console.log('Error creating namespace: ' + err)
    return new Promise(function (resolve, reject) {
      reject(new Error(`Failure creating namespace: ${namespaceName}: ${err}`))
    })
  }
// ...
}

原测试代码

jest.doMock('kubernetes-client', () => {
  const aRejection = jest.fn(() => {
    const err = new Error(404)
    err.response = 'Not found'
    err.status = 404
    err.statusCode = 404
    return Promise.reject(err)
  })
  const aPromise = jest.fn(() => {
    return Promise.resolve({
      body: {
        data: {
          username: 'dXNlcm5hbWUK' // 'username', base64-encoded
        }
      }
    })
  })
  const namespaces = jest.fn().mockReturnValue({
    get: aRejection,
    post: aPromise
  })
  const mockClient = {
    api: {
      v1: {
        namespaces
      }
    },
  }
  return {
    Client: jest.fn(() => mockClient),
  }
})

解决方法

在JavaScript中,函数本身也是对象,直接给namespaces函数对象添加post方法,就能让它同时支持函数调用和对象属性访问:

修改测试代码中的namespaces定义部分:

const namespaces = jest.fn().mockReturnValue({
  get: aRejection
})
// 给函数对象添加post方法,对应对象调用的场景
namespaces.post = aPromise

完整修改后的测试代码:

jest.doMock('kubernetes-client', () => {
  const aRejection = jest.fn(() => {
    const err = new Error(404)
    err.response = 'Not found'
    err.status = 404
    err.statusCode = 404
    return Promise.reject(err)
  })
  const aPromise = jest.fn(() => {
    return Promise.resolve({
      body: {
        data: {
          username: 'dXNlcm5hbWUK' // 'username', base64-encoded
        }
      }
    })
  })
  const namespaces = jest.fn().mockReturnValue({
    get: aRejection
  })
  // 新增:给namespaces函数添加post方法
  namespaces.post = aPromise
  
  const mockClient = {
    api: {
      v1: {
        namespaces
      }
    },
  }
  return {
    Client: jest.fn(() => mockClient),
  }
})

这样设置后:

  • 执行client.api.v1.namespaces(namespaceName).get()时,namespaces作为函数调用,返回带有get方法的对象,触发aRejection逻辑;
  • 执行client.api.v1.namespaces.post(namespaceJson)时,直接调用namespaces函数对象上的post方法,触发aPromise逻辑,不会再出现“post不是函数”的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 09:46:01