RSpec测试Rails嵌套评论创建接口报ArgumentError (given 2, expected 0)如何解决
错误根本原因
你在RSpec测试代码中,把控制器测试用来发送POST请求的内置方法post给覆盖了:
- 你通过
let(:post) { create(:post) }定义了一个名为post的变量,用来存储测试用的Post实例 - 后续你调用
post :create, params: { ... }发起请求时,实际调用的是你定义的这个Post对象,而不是RSpec提供的发请求的post方法,对象作为方法调用时不需要参数,所以你传了2个参数就抛出了参数数量不匹配的错误。
除此之外你的测试代码还存在3处逻辑错误:
- 你把创建请求写在了
let!块里,执行expect的时候不会重新触发请求,计数校验逻辑无效 - 传参时
post_id: post直接传了Post对象,应该传对象的id - 同时使用了
sign_in_user宏和手动stubcurrent_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
相关产品推荐
相关产品推荐

