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

RSpec测试Rails嵌套评论创建接口报ArgumentError (given 2, expected 0)如何解决

错误根本原因

你在RSpec测试代码中,把控制器测试用来发送POST请求的内置方法post给覆盖了:

  • 你通过let(:post) { create(:post) }定义了一个名为post的变量,用来存储测试用的Post实例
  • 后续你调用post :create, params: { ... }发起请求时,实际调用的是你定义的这个Post对象,而不是RSpec提供的发请求的post方法,对象作为方法调用时不需要参数,所以你传了2个参数就抛出了参数数量不匹配的错误。

除此之外你的测试代码还存在3处逻辑错误:

  1. 你把创建请求写在了let!块里,执行expect的时候不会重新触发请求,计数校验逻辑无效
  2. 传参时post_id: post直接传了Post对象,应该传对象的id
  3. 同时使用了sign_in_user宏和手动stub current_user,存在冗余冲突

修复方案

第一步:重命名冲突的变量名

把测试中用来存储Post实例的let变量名改成不冲突的名字,比如test_post:

# 修改前
let(:post) { create(:post) }
# 修改后
let(:test_post) { create(:post) }

第二步:修正请求逻辑和参数

把let!块里的请求逻辑移到expect的执行块中,同时把post_id改成传id:

describe 'POST #create' do
  context 'with valid attributes' do
    it 'saves the new comment in the database' do
      expect do
        post :create, params: { post_id: test_post.id, comment: attributes_for(:comment) }
      end.to change(Comment, :count).by(1)
    end
  end
end

第三步:清理冗余的登录逻辑

你已经通过sign_in_user宏完成了Devise用户登录,不需要再手动stub current_user,删掉这部分冗余代码即可:

# 删掉以下代码
setup do
  allow(controller).to receive(:current_user).and_return(user)
end

可选优化:Comment工厂里的user_id可以直接关联user对象,不需要手动取id,写法更简洁:

factory :comment do
  comment { 'Comment' }
  name { 'Name' }
  post
  user
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 06:54:04