如何用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
相关产品推荐
相关产品推荐

