Rails集成测试post方法报ArgumentError:参数数量不符问题排查
问题描述
我在集成测试中编写了发起POST请求的代码:
assert_no_difference 'User.count' do post users_path, params: { user: { name: '', email: 'user@invalid', password: 'foo', password_confirmation: 'bar' }} end
运行测试时持续报错:
ArgumentError: wrong number of arguments (given 2, expected 1)
查看堆栈跟踪发现错误源于actionpack的integration.rb中的post方法,该方法定义为:
def post(path, **args) process(:post, path, **args) end
我传入了params关键字参数,但似乎被隐式转为哈希导致报错,将方法修改为接受args参数后测试正常。想了解是否Rails存在隐式转换,问题根源是什么?
问题根源与解决方案
这个问题和Rails的隐式转换无关,核心是Ruby版本与当前使用的Rails版本不兼容。
具体原因:
- Rails里的
post方法用了Ruby 2.7及以上版本才支持的关键字参数分离语法(**args),这种语法要求调用时必须用标准的关键字参数传递,不能用旧版Ruby的哈希式写法混着传。 - 如果你用的Ruby版本低于2.7,当你写
post users_path, params: {...}时,Ruby会把params: {...}当成一个普通的哈希(也就是第二个位置参数),而不是关键字参数。但方法定义只接受1个位置参数(path)加上关键字参数,所以就会触发“参数数量不匹配”的错误。
解决方式:
- 先查Ruby版本:执行
ruby -v确认版本,要是低于2.7,要么把Ruby升级到2.7或更高版本(推荐,因为低版本Ruby已经停止维护),要么调整调用方式,严格按照关键字参数的要求传递(不过升级版本是更稳妥的长期方案)。 - 你修改方法为接受
args参数(比如改成def post(path, args = {}))能跑通,是因为这种写法兼容旧版Ruby的哈希参数传递,但这不符合Rails的标准实现,不建议长期这么改,还是对齐版本要求更靠谱。
内容的提问来源于stack exchange,提问作者testing09
相关产品推荐
相关产品推荐

