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

如何用RSpec模拟带块且从数组逐个yield的方法?

解决Ruby测试中模拟多次yield的问题

正确模拟多次yield的写法

你只需要链式调用多个and_yield,就能让被模拟的ranking_per_lanes方法依次yield每个lane对象,完全匹配原方法里的遍历逻辑:

# 先创建测试用的lane模拟实例
lane_l2 = double("Lane", percent: 30, tag: 'l2')
lane_l1 = double("Lane", percent: 10, tag: 'l1')

# 链式添加and_yield,按顺序返回需要的lane
allow(Lane).to receive(:ranking_per_lanes).and_yield(lane_l2).and_yield(lane_l1)

# 断言call方法的输出结果
expect(subject.call).to eq([[30, 'l2'], [10, 'l1']])

为什么之前的尝试失败?

  • 直接yield整个集合是错的:原方法是逐个yield单个lane对象,不是把整个集合一次性yield出去,和原逻辑不匹配。
  • 循环设置and_yield时如果多次调用allow,会覆盖之前的设置,必须在同一个allow语句里链式拼接所有and_yield。

进阶:动态处理任意数量的lane

如果测试需要处理数量不固定的lane集合,可以用reduce动态构建yield链:

# 批量创建测试用的lane实例
test_lanes = [
  double("Lane", percent: 30, tag: 'l2'),
  double("Lane", percent: 10, tag: 'l1')
]

# 动态生成链式yield逻辑
allow(Lane).to receive(:ranking_per_lanes).then do |mock_obj|
  test_lanes.reduce(mock_obj) { |mock, lane| mock.and_yield(lane) }
end

expect(subject.call).to eq([[30, 'l2'], [10, 'l1']])

这样不管test_lanes里有多少元素,都能自动按顺序逐个yield,完美复现原方法的遍历行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 01:20:32