用于为嵌套资源创建控制器操作的RSpec测试

用于为嵌套资源创建控制器操作的RSpec测试,rspec,controller,nested,Rspec,Controller,Nested,我有一个Rails应用程序(Rails 3.0.10),在这里用户可以有许多文章,并且用户可以在文章上留下评论。评论在文章展示页面上 现在我想测试CommentsController的创建操作,但是,我在使用正确的参数调用post方法时遇到了问题 以下是CommentsController的代码: class CommentsController < ApplicationController # create a comment and bind it to an article

我有一个Rails应用程序(Rails 3.0.10),在这里用户可以有许多文章,并且用户可以在文章上留下评论。评论在文章展示页面上

现在我想测试CommentsController的创建操作,但是,我在使用正确的参数调用post方法时遇到了问题

以下是CommentsController的代码:

class CommentsController < ApplicationController

  # create a comment and bind it to an article and a user  
  def create
    @article = Article.find(params[:article_id])
    @user = User.find(@article.user_id)
    @comment = @article.comments.build(params[:comment])
    @comment.user_id = current_user.id

    commenters = [] 
    @article.comments.each {
      |comment|
      commenters << User.find(comment.user_id)
    }
    commenters.uniq!

    respond_to do |format|
      if @comment.save        

        #Notify user who offers article on new comment, else notify the commenters
        if @article.user_id != @comment.user_id
          UserMailer.new_article_comment_email(@user, @comment).deliver
        else        
          commenters.each {
            |commenter|
            UserMailer.new_article_comment_email(commenter, @comment).deliver
          }
        end

        format.html { 
          redirect_to(@article)
          flash[:notice] = t(:comment_create_success)
        }
      else
        format.html { 
          redirect_to(@article) 
          flash[:error] = t(:comment_create_error)
        }
      end
    end
  end
end
但是,由于我无法修复的不同原因,两个测试均失败:

    Failures:

      1) CommentsController POST 'create' should create a new comment
         Failure/Error: post :create, :comment => @comment_attributes
         ActionController::RoutingError:
           No route matches {:comment=>{:body=>"This is the body text of a comment"}, :controller=>"comments", :action=>"create"}
         # ./spec/controllers/comments_controller_spec.rb:22:in `block (4 levels) in <top (required)>'
         # ./spec/controllers/comments_controller_spec.rb:21:in `block (3 levels) in <top (required)>'

      2) CommentsController POST 'create' should create a new comment, redirect to the article show page of this comment and notify the user on successful saving of the comment
         Failure/Error: post :create, :comment => @comment_attributes, :article_id => @article.id.to_s, :user_id => @user.id.to_s
         RuntimeError:
           Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
         # ./app/controllers/comments_controller.rb:8:in `create'
         # ./spec/controllers/comments_controller_spec.rb:27:in `block (3 levels) in <top (required)>'
更新:以下是我根据NMOTS建议所做的修改:

require 'spec_helper'
require 'ruby-debug'

describe CommentsController do
  render_views

  describe "POST 'create'" do

    before(:each) do
      @user = FactoryGirl.create(:user)

      @article = FactoryGirl.build(:article)
      @article.user_id = @user.id
      @article.save

      @comment_attributes = FactoryGirl.attributes_for(:comment, :article_id => @article)
    end

    it "should create a new comment" do
      post :create, :article_id => @article.id.to_s, :comment => @comment_attributes
    end

  end

end
以及FactoryGirl的定义供评论:

factory :comment do
  body "This is the body text of a comment"
  article
end

不幸的是,代码还没有工作

对于嵌套资源,您需要构造设置数据和帖子,以便在发布子评论时识别父文章

一种方法是正确设置Factory Girl关联,然后确保在创建子属性时设置父元素。它看起来像这样:

在注释工厂中:

FactoryGirl.define do
  Factory :comment do
    comment "My comment"
    article
  end
end
通过调用article并确保存在名为
:article
的有效工厂,FactoryGirl将在创建注释时创建一篇文章。为了使测试顺利进行,我们实际上应该明确在创建
注释时使用了哪些
文章
,因此现在工厂已经就位,我们在规范中使用了以下内容

@comment_attributes = FactoryGirl.attributes_for(:comment, :article_id => @article)
这将生成自动附加到@article的注释属性。最后一个部分是构建post,确保我们包括父对象和子对象

发布嵌套资源时,父资源和子资源都需要参数。在rspec中,我们可以在帖子中提供以下信息:

post :create, :article_id => @article, :comment => @comment_attributes

这应该可以正确地连接所有部分。

我用完整路线更新了我的帖子。rbnmott谢谢你,有了你的解释,事情对我来说就更清楚了。不幸的是,它还没有成功。我根据你上面的建议发布了我的更改。好的,我现在开始工作了。问题是只有登录用户才能发表评论。因此,问题不仅在于如何测试嵌套的控制器,而且在测试嵌套的注释控制器之前,有必要创建一个测试用户并登录该用户。
@comment_attributes = FactoryGirl.attributes_for(:comment, :article_id => @article)
post :create, :article_id => @article, :comment => @comment_attributes