使用和测试Rails ActionController的respond_with

时间:2010-11-29 23:54:29

标签: ruby-on-rails rspec actioncontroller respond-to respond-with

提前为这个问题的冗长道歉。如果你忍受我,我想你会发现它实际上非常简单......由于我有限的Rails领域知识,我很难解释。

an ActionController commit dated Aug 6中给出此评论:

 === Builtin HTTP verb semantics

 Rails default renderer holds semantics for each HTTP verb. Depending on the
 content type, verb and the resource status, it will behave differently.

 Using Rails default renderer, a POST request for creating an object could
 be written as:

   def create   
     @user = User.new(params[:user])    
     flash[:notice] = 'User was successfully created.' if @user.save
     respond_with(@user)
       end

 Which is exactly the same as:

   def create
     @user = User.new(params[:user])

     respond_to do |format|
       if @user.save
         flash[:notice] = 'User was successfully created.'
         format.html { redirect_to(@user) }
         format.xml { render :xml => @user, :status => :created, :location => @user }
       else
         format.html { render :action => "new" }
         format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
       end
     end
   end

 The same happens for PUT and DELETE requests.

我修改了一个非常基本的控制器来使用respond_with。一切似乎工作正常,除了Rails自动生成的测试尝试将空params传递给更新&创造方法。我可以通过简单的if save / else来纠正这种行为但是我正试图理解这个“新”功能。我认为默认规范可能是以过时的方式编写的。

来自提交评论:“Since the request is a POST, respond_with will check wether @people resource have errors or not. If it has errors, it will render the error object with unprocessable entity status (422).

因此,向下滚动到POST(下面)下的最后一个测试/规范,我是否可以重新编写它,以便测试“不可处理的实体状态(422)”并通过,因此一切都是非常敏锐的?

我的控制器:

class ClownsController < ApplicationController
  respond_to :html, :json

  def index
    respond_with(@clowns = Clown.all)
  end

  def show
    respond_with(@clown = Clown.find(params[:id]))
  end

  def new
    respond_with(@clown = Clown.new)
  end

  def edit
    respond_with(@clown = Clown.find(params[:id]))
  end

  def create
     @clown = Clown.new(params[:clown])
     flash[:notice] = 'Clown was successfully created.' if @clown.save
     respond_with(@clown) 
  end

  # Replacing def create above with this won't Fail the spec ##
  #
  # def create
  #    @clown = Clown.new(params[:clown])
  #    respond_with(@clown) do |format|
  #      if @clown.save
  #        flash[:notice] = 'Clown was successfully created.'
  #        format.html { redirect_to @clown }
  #      else
  #        format.html { render :action => :new }
  #      end
  #    end
  # end


  def update
    @clown = Clown.find(params[:id])
    flash[:notice] = 'Clown has been updated.' if @clown.update_attributes(params[:clown])
    respond_with(@clown)
  end

  def destroy
    @clown = Clown.find(params[:id])
    flash[:notice] = 'Successfully deleted clown.' if @clown.destroy
    respond_with(@clown)
  end
end

测试规格:

$ rspec spec/
.......F....F..............

Failures:

  1) ClownsController POST create with invalid params re-renders the 'new' template
     Failure/Error: response.should render_template("new")
     expecting <"new"> but rendering with <"">.
     Expected block to return true value.
     # (eval):2:in `assert_block'
     # ./spec/controllers/clowns_controller_spec.rb:69:in `block (4 levels) in <top (required)>'

  2) ClownsController PUT update with invalid params re-renders the 'edit' template
     Failure/Error: response.should render_template("edit")
     expecting <"edit"> but rendering with <"">.
     Expected block to return true value.
     # (eval):2:in `assert_block'
     # ./spec/controllers/clowns_controller_spec.rb:107:in `block (4 levels) in <top (required)>'

以下是clowns_controller_spec.rb的一部分:

require 'spec_helper'

describe ClownsController do

  def mock_clown(stubs={})
    (@mock_clown ||= mock_model(Clown).as_null_object).tap do |clown|
      clown.stub(stubs) unless stubs.empty?
    end
  end

...

  describe "POST create" do

    describe "with invalid params" do    
      it "re-renders the 'new' template" do
        Clown.stub(:new) { mock_clown(:save => false) }
        post :create, :clown => {}
        response.should render_template("new")
      end
    end

1 个答案:

答案 0 :(得分:2)

尝试使用以下

模拟您的Clown课程
Clown.stub(:new) { mock_clown(:errors => {:any => 'error'}) }

这样,respond_with方法将知道模型保存失败并且它将呈现新模板。