rspec controller spec matchers

2019-08-18 01:47发布

With which matcher and how can I test if the @post_comment and @post_comment.user is properly assigned?

expect(assigns(:post_comment)).to be_a_new(PostComment) is not working here.

UPDATE:

With the following setup I also get the following error. What should I change to be able to test the invalid attrs?

Posts::PostCommentsController when user is logged in POST create with invalid attributes doesn't save the new product in the db
 Failure/Error: @post_comment.save!

 ActiveRecord::RecordInvalid:
   Validation failed: Body can't be blank

IF I delete @post_comment.save! then I get

Posts::PostCommentsController when user is logged in POST create with invalid attributes doesn't save the new product in the db
 Failure/Error: <span class="post-comment-updated"><%= local_time_ago(post_comment.updated_at) %></span>

 ActionView::Template::Error:
   undefined method `to_time' for nil:NilClass

post_comments_controller

  def create
    @post = Post.find(params[:post_id])
    @post_comment = @post.post_comments.build(post_comment_params)
    authorize @post_comment
    @post_comment.user = current_user
    @post_comment.save!
    if @post_comment.save
      @post.send_post_comment_creation_notification(@post_comment)
      @post_comment_reply = PostCommentReply.new
      respond_to do |format|
        format.html { redirect_to posts_path, notice: "Comment saved!" }
        format.js
      end
    end
  end

post_comments_controller_spec.rb

describe "POST create" do
  let!(:profile) { create(:profile, user: @user) }
  let!(:post_instance) { create(:post, user: @user) } 

  context "with valid attributes" do
    subject(:create_action) { xhr :post, :create, post_id: post_instance.id, post_comment: attributes_for(:post_comment, post_id: post_instance.id, user: @user) }

    it "saves the new task in the db" do
      expect{ create_action }.to change{ PostComment.count }.by(1)
    end

    it "assigns instance variables" do
      create_action
      expect(assigns(:post)).to eq(post_instance)
      #########How to test these two?
      #expect(assigns(:post_comment)).to be_a_new(PostComment)
      #expect(assigns(:post_comment.user)).to eq(@user)
      expect(assigns(:post_comment_reply)).to be_a_new(PostCommentReply)
    end

    it "assigns all the instance variables"

    it "responds with success" do
      create_action
      expect(response).to have_http_status(200)
    end
  end

  context "with invalid attributes" do
    subject(:create_action) { xhr :post, :create, post_id: post_instance.id, post_comment: attributes_for(:post_comment, post_id: post_instance.id, user: @user, body: "") }

    it "doesn't save the new product in the db" do
      expect{ create_action }.to_not change{ PostComment.count }
    end
  end
end

1条回答
聊天终结者
2楼-- · 2019-08-18 02:39
  1. How to test these two?

    expect(assigns(:post_comment)).to be_a_new(PostComment)
    expect(assigns(:post_comment.user)).to eq(@user)
    

    I believe you shoudl test not a new record, but a record of a class, and persisted record:

    expect(assigns(:post_comment)).to be_a(PostComment)
    expect(assigns(:post_comment)).to be_presisted
    expect(assigns(:post_comment.user)).to eq(@user)
    
  2. Excessive code.

    @post_comment.save!
    if @post_comment.save
    

    You shall to keep only the single record of that, I believe it is enough save with exception:

    @post_comment.save! 
    

    So other part code you can pick out of if block. Exception from save! you shall to trap with rescue_from.

查看更多
登录 后发表回答