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

如何在RSPEC中Stub ShopifyAPI::DraftOrder的find/all方法并返回静态哈希

模拟ShopifyAPI::DraftOrder返回静态数据的正确方式

你遇到的问题核心在于:ShopifyAPI的DraftOrder是ActiveResource模型,它的find/all方法返回的是模型实例(或实例数组),而非普通Ruby哈希。直接返回哈希会导致后续代码调用实例方法(比如.id、.attributes)时抛出NoMethodError,这就是你的mock没生效的关键原因。

下面是两种可行的实现方案:

方案一:使用模拟实例(Double)

适合需要精细控制实例方法返回值的场景:

# 1. 定义你的静态哈希数据
static_draft_order_hash = {
  id: 123,
  name: "Draft Order #1",
  email: "customer@example.com",
  # 其他你需要的字段
}

# 2. 创建模拟的DraftOrder实例
mock_draft_order = double("ShopifyAPI::DraftOrder")
# 模拟attributes方法返回静态哈希
allow(mock_draft_order).to receive(:attributes).and_return(static_draft_order_hash)
# 如果你的代码直接调用实例属性(比如`.id`、`.name`),单独模拟这些方法
allow(mock_draft_order).to receive(:id).and_return(static_draft_order_hash[:id])
allow(mock_draft_order).to receive(:name).and_return(static_draft_order_hash[:name])

# 3. 模拟find方法返回这个实例
allow(ShopifyAPI::DraftOrder).to receive(:find).with(draft_id).and_return(mock_draft_order)

对于all方法(返回实例数组):

# 定义多个静态哈希
draft_order_hashes = [
  { id: 123, name: "Order 1" },
  { id: 456, name: "Order 2" }
]

# 创建模拟实例数组
mock_draft_orders = draft_order_hashes.map do |hash|
  mock = double("ShopifyAPI::DraftOrder")
  allow(mock).to receive(:attributes).and_return(hash)
  allow(mock).to receive(:id).and_return(hash[:id])
  mock
end

# 模拟带参数的all调用
allow(ShopifyAPI::DraftOrder).to receive(:all).with(params: {page: 1, status: 'any'}).and_return(mock_draft_orders)
# 模拟不带参数的all调用
allow(ShopifyAPI::DraftOrder).to receive(:all).and_return(mock_draft_orders)

方案二:直接实例化ShopifyAPI::DraftOrder

如果不需要精细控制方法,直接用真实的模型实例更简单:

# 1. 定义静态哈希
static_draft_order_hash = { id: 123, name: "Draft Order #1" }

# 2. 创建DraftOrder实例并赋值属性
mock_draft_order = ShopifyAPI::DraftOrder.new(static_draft_order_hash)
# 模拟find方法
allow(ShopifyAPI::DraftOrder).to receive(:find).with(draft_id).and_return(mock_draft_order)

# 对于all方法,返回实例数组
mock_draft_orders = [
  ShopifyAPI::DraftOrder.new({ id: 123, name: "Order 1" }),
  ShopifyAPI::DraftOrder.new({ id: 456, name: "Order 2" })
]
allow(ShopifyAPI::DraftOrder).to receive(:all).with(params: {page: 1, status: 'any'}).and_return(mock_draft_orders)

额外排查点

如果按照上面的方式还是没生效,检查以下两点:

  • 参数匹配是否完全一致:比如all方法的params里的键值对是否和实际调用完全相同(比如page是整数还是字符串?有没有额外的参数?)。RSpec的with是严格匹配的,参数不匹配会导致mock不触发,转而调用真实API。
  • 是否有重复的mock:如果之前已经对ShopifyAPI::DraftOrder的方法做过mock,后面的mock可能会被覆盖或者冲突,检查测试用例里的mock顺序。

内容的提问来源于stack exchange,提问作者aldrien.h

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:29:29