RSpec Newbie: «Обновить атрибуты => ложь» не распознается - PullRequest
4 голосов
/ 14 января 2011

Просто начинаю с RSpec. Все идет гладко, за исключением одной спецификации с вложенными контроллерами.

Я пытаюсь обеспечить, чтобы при обновлении ресурса 'comment' (вложенного в 'post') недопустимыми параметрами он отображал шаблон 'edit' Я пытаюсь заставить rspec распознать триггер: update_attributes => false. Если у кого-то есть какие-либо предложения, они будут очень благодарны. Попытка кода ниже:

  def mock_comment(stubs={})
    stubs[:post] = return_post
    stubs[:user] = return_user
    @mock_comment ||= mock_model(Comment, stubs).as_null_object
  end

  describe "with invalid paramters" dog
    it "re-renders the 'edit' template" do
      Comment.stub(:find).with("12") { mock_comment(:update_attributes => false) }
      put :update, :post_id => mock_comment.post.id, :id => "12"
      response.should render_template("edit")
    end
  end

И контроллер:

  def update
    @comment = Comment.find(params[:id])
    respond_to do |format|
      if @comment.update_attributes(params[:comment])
        flash[:notice] = 'Post successfully updated'
        format.html { redirect_to(@comment.post) }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @comment.errors, :status => :unprocessable_entity }
      end
    end

  end

И, наконец, ошибка:

 Failure/Error: response.should render_template("edit")
   expecting <"edit"> but rendering with <"">.
   Expected block to return true value.

1 Ответ

5 голосов
/ 15 января 2011

Это довольно интересная проблема.Быстрое решение состоит в том, чтобы просто заменить блочную форму Comment.stub:

Comment.stub(:find).with("12") { mock_comment(:update_attributes => false) }

на явную and_return:

Comment.stub(:find).with("12").\
  and_return(mock_comment(:update_attributes => false))

Почему эти две формы должны давать разные результатыЭто немного головокружение.Если вы поэкспериментируете с первой формой, то увидите, что mock на самом деле возвращает self вместо false при вызове метода-заглушки.Это говорит нам о том, что он не заглушил метод (поскольку он указан как нулевой объект).

Ответ заключается в том, что при передаче в блоке блок выполняется только при вызове метода с заглушкой, а не когдазаглушка определена.Поэтому при использовании блочной формы следующий вызов:

put :update, :post_id => mock_comment.post.id, :id => "12"

выполняется mock_comment в первый раз.Поскольку :update_attributes => false не передается, метод не заглушается, и вместо false возвращается mock.Когда блок вызывает mock_comment, он возвращает @mock_comment, в котором нет заглушки.

Наоборот, использование явной формы and_return вызывает mock_comment немедленно.Вероятно, было бы лучше использовать переменную экземпляра вместо вызова метода каждый раз, чтобы сделать намерение более понятным:

it "re-renders the 'edit' template" do
  mock_comment(:update_attributes => false)
  Comment.stub(:find).with("12") { @mock_comment }
  put :update, :post_id => @mock_comment.post.id, :id => "12"
  response.should render_template("edit")
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...