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

Rspec模拟初始化时哈希被识别为关键字参数的问题解决

Rails 7.1.3升级后RSpec Mock位置哈希参数被识别为关键字参数的解决方法

问题场景

升级至Rails 7.1.3后,定义的类初始化方法同时包含带默认空哈希的位置参数和关键字参数:

def initialize(opts = {}, foo: :bar)

在RSpec测试中Mock该初始化方法时,传入哈希作为位置参数:

options = {cow: "over", moon: "under"}
expect(Thing).to(receive(:new).with(options))

触发错误:RSpec::Mocks::MockExpectationError: Invalid keyword arguments provided: cow, moon,哈希被错误识别为关键字参数。

已尝试的无效方案:

  • 将哈希存入变量后传递给with方法
  • 在with和new调用中添加关键字参数
  • 移除默认空哈希参数(可通过测试但不符合业务需求)

解决方法

方法1:使用精确匹配器明确指定位置参数

通过eq()匹配器告诉RSpec,第一个参数是完全匹配的哈希:

expect(Thing).to receive(:new).with(eq(options))

如果只需要验证哈希包含指定键值对,可改用hash_including():

expect(Thing).to receive(:new).with(hash_including(cow: "over"))

方法2:通过块验证参数类型与内容

使用块接收调用时的参数,手动验证位置参数和关键字参数:

expect(Thing).to receive(:new) do |opts, **kwargs|
  expect(opts).to eq(options)
  expect(kwargs).to be_empty # 根据实际需求验证关键字参数
end

方法3:指定参数类型匹配器

如果只需要验证第一个参数是哈希类型,可使用instance_of(Hash):

expect(Thing).to receive(:new).with(instance_of(Hash))

可复现最小代码

class Thing
  def initialize(opts = {}, foo: "bar")
  end
end

require "rspec"

describe Thing do
  let(:options) { {cow: "over", moon: "below"} }

  it "mocks out the initialize" do
    # 替换为上述解决方法中的expect语句即可通过测试
    expect(Thing).to receive(:new).with(eq(options))

    Thing.new(options)
  end
end

相关Gem版本

rails (7.1.3)
rspec (3.13.0)
rspec-core (3.13.0)
rspec-expectations (3.13.0)
rspec-mocks (3.13.0)
rspec-rails (6.1.0)
rspec-retry (0.6.2)
rspec-support (3.13.0)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 00:34:55