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

如何用RSpec构造Stripe Ruby Gem模拟响应的存根返回值?

如何用RSpec构造Stripe Ruby Gem模拟响应的存根返回值?

哈哈,我太懂这个坑了!Stripe的Ruby SDK对象可不是普通的Ruby类,直接用Stripe::Customer.new确实会踩NoMethodError的坑,因为它们是基于API响应的JSON数据构建的,有自己的一套属性处理逻辑。下面给你两种靠谱的解决办法:

方法一:用Stripe内部工具方法构建真实Stripe对象

Stripe提供了一个内部方法Stripe::Util.convert_to_stripe_object,专门用来把普通哈希转换成对应的Stripe SDK对象,这样你得到的实例就和真实API返回的对象行为完全一致:

# 先构造你需要模拟的响应哈希
customer_data = {
  id: "cus_NF2qXZzjMAfqMr",
  email: "my@randomemail.com",
  object: "customer",
  account_balance: 0,
  address: { city: "SF", country: "United States", line1: "2C", postal_code: "11111", state: "CA" },
  # 按需添加其他你需要测试的字段
}

# 把哈希转换成Stripe::Customer实例
stubbed_customer = Stripe::Util.convert_to_stripe_object(customer_data, {}, Stripe::Customer)

# 然后在RSpec里存根方法调用
allow(Stripe::Customer).to receive(:retrieve).with("cus_NF2qXZzjMAfqMr").and_return(stubbed_customer)

这样你在测试代码里调用stubbed_customer.email或者stubbed_customer.address.city时,就和真实场景完全一样了。

方法二:用RSpec双精度对象(Double)轻量模拟

如果你的测试只需要用到Stripe对象的部分属性,不需要完整的Stripe实例行为,那用RSpec的double来模拟会更轻量:

# 模拟地址子对象
stubbed_address = double("Stripe::Address", city: "SF", country: "United States")

# 模拟Customer对象,只定义你需要用到的属性
stubbed_customer = double("Stripe::Customer",
  id: "cus_NF2qXZzjMAfqMr",
  email: "my@randomemail.com",
  address: stubbed_address,
  account_balance: 0
)

# 存根方法调用
allow(Stripe::Customer).to receive(:retrieve).and_return(stubbed_customer)

这种方式的好处是不需要依赖Stripe内部的转换逻辑,只模拟你测试中实际用到的属性,测试运行速度也更快。

为什么直接new不行?

补充一句:Stripe SDK的new方法并没有实现用keyword arguments初始化属性的逻辑,它的实例属性是从API返回的JSON数据中解析出来的,所以直接Stripe::Customer.new(email: 'xxx')不会给实例设置email属性,自然会报NoMethodError啦。

备注:内容来源于stack exchange,提问作者iftheshoefritz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 15:19:09