2

ポリモーフィック コメント コントローラー内で POST create アクションをテストしようとしています。以下の仕様を実行すると、次のエラーで失敗します。

undefined method `comments' for nil:NilClass

これは、@commentable が適切に作成/設定されていないため、存在しないことを意味すると思います。ATMload_commentableメソッドをスタブアウトして FactoryGirl 質問オブジェクトを返していますが、これでもまだ何も解決していないようです。

コメント可能なオブジェクトが適切に作成され、実際のコントローラーのように @commentable のスコープ内でコメントが作成されるように、仕様を修正するにはどうすればよいですか?

コメント_コントローラー.rb

def create 
    @comment = @commentable.comments.build(params[:comment])
    @comment.user_id = current_user.id
    respond_to do |format|
    if @comment.save
        format.html { redirect_to @commentable, notice: 'Comment created'}
        format.js
    else
      format.html { redirect_to @commentable, notice: "Content can't be blank" }
      format.js
      end
    end
  end

def load_commentable
    resource, id = request.path.split('/')[1,2]
    @commentable = resource.singularize.classify.constantize.find(id)
  end

comments_controller_spec.rb

describe CommentsController do
  include Devise::TestHelpers
  include AnswerHelper
  before(:each) do
    @user = create(:user)
    @user2 = create(:user)
    sign_in @user
    sign_in @user2
    @commentable = create(:question, user: @user2)
    @comment = create(:comment, user: @user)
    @vote = attributes_for(:vote, user: @user2, votable_id: @commentable)
    controller.stub!(:load_commentable).and_return(@commentable)
    controller.stub!(:current_user).and_return(@user)
    @request.env['HTTP_REFERER'] = "http://test.host/questions/#{@commentable.id}"
    stub_model_methods
  end

  describe "POST create" do
    describe "with valid params" do
      it "creates a new comment" do
        expect {
          post :create, comment: attributes_for(:comment), commentable: @commentable
        }.to change(Comment, :count).by(1)
      end

      it "assigns a newly created comment as @comment" do
        post :create, comment: attributes_for(:comment), commentable: @commentable
        assigns(:comment).should be_a(Comment)
        assigns(:comment).should be_persisted
      end
    end

    describe "with invalid params" do
      it "assigns a newly created but unsaved comment as @comment" do
        Comment.any_instance.stub(:save).and_return(false)
        post :create, comment: attributes_for(:comment), commentable: @commentable
        assigns(:comment).should be_a_new(Comment)
      end
    end
  end

factory.rb

factory :comment do
    user
    commentable_id :question
    commentable_type "Question"
    content "a comment"
    votes_count 5
  end

rspec の結果

1) CommentsController POST create with valid params creates a new comment
     Failure/Error: post :create, comment: attributes_for(:comment), commentable: @commentable
     NoMethodError:
       undefined method `comments' for nil:NilClass
     # ./app/controllers/comments_controller.rb:19:in `create'
     # ./spec/controllers/comments_controller_spec.rb:24:in `block (5 levels) in <top (required)>'
     # ./spec/controllers/comments_controller_spec.rb:23:in `block (4 levels) in <top (required)>'
4

1 に答える 1

1

ここでの問題は、コントローラーでインスタンス変数を設定する責任がある load_commentable をスタブ化していることです@commentable。スタブしているため、呼び出されることはなく、ivar が設定されることもありません。rspec テスト スイートからコントローラーに ivar を直接設定することはできません。

レコードを作成しているので、実際には何もスタブする必要はなく、 を渡すだけ@commentable.idでデータベースから検索できます。ただし、何らかの理由で検索を回避したい場合は、次を使用できます。

Question.stub(:find).with(@commentable.id).and_return(@commentable)

これにより、コントローラーが@commentableオブジェクトを使用し、コントローラーに割り当てます@commentable。この時点で、テストは引き続き正常に実行されます。

于 2013-06-29T15:38:52.897 に答える