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

如何用RSpec测试get_input方法内部递归调用自身的逻辑

解决方案

你原来的用例存在两个核心问题:

  1. 你设置的断言只要求get_input至少被调用1次,你手动触发的game_input.get_input本身就满足了这个条件,所以不管方法内部有没有触发递归,用例都会通过
  2. 你把valid_input?桩定为永远返回false,如果不打断递归链,用例运行时会无限调用get_input,最终触发栈溢出报错

你可以用RSpec的有序调用断言来实现需求,既能验证递归调用的存在,又能避免无限循环:

describe '#get_input' do
  subject(:game_input) { described_class.new(1, 2) }

  it 'recursively calls itself when input is invalid' do
    # 桩定输入永远无效
    allow(game_input).to receive(:valid_input?).and_return(false)
    
    # 第一次调用为手动触发,走原方法逻辑验证分支
    expect(game_input).to receive(:get_input).ordered.and_call_original
    # 第二次调用为内部递归,直接返回终止递归,不需要走原逻辑
    expect(game_input).to receive(:get_input).ordered.and_return(nil)

    # 手动触发第一次调用
    game_input.get_input
  end
end

逻辑说明

  • ordered参数会严格匹配调用顺序,只有当get_input确实被调用了两次,用例才会通过:第一次是你手动触发的,第二次是方法内部递归发起的
  • 第二次调用直接返回nil,不会进入原方法的递归逻辑,从根源避免了无限循环
  • 如果你需要验证递归次数更多的场景,只需要按顺序增加对应的expect规则即可

如果不想用有序断言,也可以用调用次数断言实现同样的效果:

it 'recursively calls itself when input is invalid' do
  allow(game_input).to receive(:valid_input?).and_return(false)
  # 总共调用2次,第一次走原方法,第二次直接返回
  expect(game_input).to receive(:get_input).twice.and_call_original
  allow(game_input).to receive(:get_input).and_return(nil)

  game_input.get_input
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 22:36:03