Работа с Rails и тестирование ActionController - PullRequest
3 голосов
/ 30 ноября 2010

Заранее извиняюсь за многословность этого вопроса. Если вы потерпите меня, я думаю, вы обнаружите, что на самом деле это довольно просто ... мне сложно объяснить, учитывая мои ограниченные знания в области Rails.

С учетом этого комментария в коммит ActionController от 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 для обновления и создания методов. Я могу исправить это поведение с помощью простой команды 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 Ответ

2 голосов
/ 07 марта 2012

Попробуйте смоделировать ваш класс Clown с помощью следующего

Clown.stub(:new) { mock_clown(:errors => {:any => 'error'}) }

. Таким образом, метод response_with будет знать, что сохранение модели не удалось, и отобразит новый шаблон.

...