首页 > 解决方案 > Rspec ArgumentError:参数数量错误(给定 2,预期为 0)

问题描述

我对嵌套对象(评论)进行了 rspec 测试,它嵌套在帖子对象中。这是routes.rb:

  use_doorkeeper

  resources :posts do
    resources :comments 
  end

  root "posts#index"
end

这是评论控制器的一部分:

 class CommentsController < ApplicationController
  before_action :find_comment, only: [:destroy]
  before_action :authenticate_user!, only: [:destroy]

  def create
    @post = Post.find(params['post_id'])
    @comment = @post.comments.create(params[:comment].permit(:name, :comment, :user_id, :best, :file))
    respond_to do |format|
      format.html { redirect_to post_path(@post) }
      format.js
    end
  end
  private

  def find_comment
    @post = Post.find(params[:post_id])
    @comment = @post.comments.find(params[:id])
  end
end

这是 rspec 测试:

 require 'rails_helper'

    RSpec.describe CommentsController, type: :controller do
      let(:user) { create(:user) }
      let(:post) { create(:post) }
    
      sign_in_user
    
      setup do
        allow(controller).to receive(:current_user).and_return(user)
      end
    
      describe 'POST #create' do
        context 'with valid attributes' do
          let!(:posts) { post :create, params: { post_id: post, comment: attributes_for(:comment) } }
    
          it 'saves the new comment in the database' do
            expect {{ comment: attributes_for(:comment) } }.to change(Comment, :count).by(1)
          end
        end
      end
    
    end

用于评论的附加工厂文件:

 FactoryBot.define do
  factory :comment do
    comment { 'Comment' }
    name { 'Name' }
    post
    user_id { create(:user).id }
  end
end

授权用户的宏:

 module ControllerMacros
  def sign_in_user
    before do
      @user = create(:user)
      @request.env['devise.mapping'] = Devise.mappings[:user]
      sign_in @user
    end
  end
end

所以当我运行规范测试时,我得到了这个错误:

 ArgumentError: wrong number of arguments (given 2, expected 0)

可能是什么问题,为什么我不能运行 CREATE rspec?

标签: ruby-on-railsrspecrspec-rails

解决方案


你有几件事在这里发生。该错误是因为您的let(:post)记忆助手覆盖了post方法的名称。所以,当你打电话给它时,post :create ...它是非常不高兴的。因此,您只需要将记忆化助手的名称更改为:post.

第二个问题是你的期望永远不会过去:

expect {{ comment: attributes_for(:comment) } }.to change(Comment, :count).by(1)

当您使用该expect {}...to change()表单时,RSpec 会逐字检查expect块内的内容是否驱动了指定的更改。在您的情况下,期望块内的代码不会在数据库中创建评论记录,它只是返回模拟评论的属性哈希,因此它永远不会通过。您确实在上下文块的开头创建了一个新的评论,但它不计算在内,因为它在expect块之外。

解决这个问题的一种方法是简单地将 POST 移动到期望块中:

RSpec.describe CommentsController, type: :controller do
  let(:user) { create(:user) }
  let(:faux_post) { create(:post) } // Different name to avoid clash

  // ... stuff omitted
  
  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: faux_post, comment: attributes_for(:comment) }
        end.to change(Comment, :count).by(1)
      end
    end
  end
end

推荐阅读