FactoryBot使用initialize_with触发参数错误,是否不支持该特性?
FactoryBot初始化带关键字参数的类报错分析
问题场景
定义了仅接受关键字参数的URL类:
class URL attr_reader :description attr_reader :url def initialize(description:, url:) end end
对应的FactoryBot工厂定义:
FactoryBot.define do factory :url, class: URL do description { 'test_description' } url { 'test_url' } initialize_with { new(description: description, url: url) } end end
运行时抛出异常:
ArgumentError: wrong number of arguments (given 1, expected 0; required keywords: description, url)
尝试改用initialize_with { new(**attributes) },报错情况一致。当前环境:factory_bot 6.2.1、ruby 3.0.4
问题原因
这不是FactoryBot不支持关键字参数特性,而是Ruby 3.0对关键字参数的处理逻辑做了重大调整——Ruby 3.0将关键字参数与普通哈希参数彻底分离,不再自动把哈希转换成关键字参数。而FactoryBot 6.2.1版本的内部参数传递逻辑,会把attributes作为普通哈希(位置参数)传递给new方法,不符合URL#initialize对关键字参数的要求,因此触发参数数量不匹配的错误。
解决方法
- 显式转换参数格式
修改initialize_with的代码,确保将哈希参数展开为关键字参数:
initialize_with { new(**attributes.symbolize_keys) }
或者直接显式指定参数传递,避免歧义:
initialize_with { URL.new(description: description, url: url) }
- 升级FactoryBot版本
FactoryBot 7.x及以上版本已经适配了Ruby 3.0+的关键字参数处理逻辑,升级后无需修改现有工厂代码即可正常运行。
内容的提问来源于stack exchange,提问作者ngcable
相关产品推荐
相关产品推荐

