Подтвердить что ты не робот

Как написать RSpec-тест для простого обновления PUT?

Я пытаюсь укрепить свое понимание рельсов и рабочего процесса BDD, поэтому я хотел начать с малого, создав один из этих мини-блогов, но с rspec. Сейчас у меня есть модель ArticleController и Article, а также связанные с ней файлы rspec. Статья очень проста, имеет только название: строка и контент: текст, а ArticlesController - RESTful - хотя я вручную написал MCV для статьи, он в основном такой же, как если бы я использовал эшафот для его создания.

Однако я не знаю, что я делаю, когда дело доходит до написания теста в rspec для обновления PUT. Я использую Factory Girl для создания объекта статьи, и до сих пор мой код выглядит следующим образом:

#factories.rb
FactoryGirl.define do
  factory :article do
  title "a title"
  content "hello world"
end

#articles_controller_spec.rb
before(:each) do
  @article = Factory(:article)
end

describe "PUT 'update/:id'" do
  it "allows an article to be updated" do
    @attr = { :title => "new title", :content => "new content" }
    put :update, :id => @article.id, :article => @attr
    response.should be_successful
  end
end

Однако я продолжаю получать:

Failures:
1) ArticlesController PUT 'update/:id' allows an article to be updated
   Failure/Error: response.should be_successful
     expected successful? to return true, got false

Что я делаю неправильно? И использую ли я правильные инструменты? Когда я запускаю свой тестовый сервер, New, Edit, Destroy, все работают так, как я ожидал бы, поэтому я предполагаю, что это проблема с моим пониманием RSpec. Дайте мне знать, если я ошибаюсь - спасибо!

4b9b3361

Ответ 1

Вы забыли .reload ваш @article, а при действии update ваш ответ скорее всего выполнит перенаправление, поэтому

RSpec 2:

describe "PUT update/:id" do
  let(:attr) do 
    { :title => 'new title', :content => 'new content' }
  end

  before(:each) do
    put :update, :id => @article.id, :article => attr
    @article.reload
  end

  it { response.should redirect_to(@article) }
  it { @article.title.should eql attr[:title] }
  it { @article.content.should eql attr[:content] }
end

Rspec 3:

describe "PUT update/:id" do
  let(:attr) do 
    { :title => 'new title', :content => 'new content' }
  end

  before(:each) do
    put :update, :id => @article.id, :article => attr
    @article.reload
  end

  it { expect(response).to redirect_to(@article) }
  it { expect(@article.title).to eql attr[:title] }
  it { expect(@article.content).to eql attr[:content] }
end

Ответ 2

Когда вы делаете PUT :update, помните, что вы редактируете существующую модель, которую нужно вызвать в put. Просто передайте @article и обновите атрибуты следующим образом.

describe "PUT 'update/:id'" do
  it "allows an article to be updated" do
    put :update, :id => @article.id, :article => @article.attributes = { :title => "new title", :content => "new content" }
    response.should be_successful
  end
end

Ответ 3

FactoryGirl.define :article do
  title "a title"
  content "hello world"
end

before(:each) do
  @article = Factory(:article)
end

it "should re-render edit template on failed update" do
  @attr = { :title => "", :content => "new content" }
  put :update, :id => @article.id, :article => @attr

  flash[:notice].should be_nil
  response.should render_template('edit')
end

it "should redirect to index with a notice on successful update" do
  @attr = { :title => "new title", :content => "new content" }
  put :update, :id => @article.id, :article => @attr

  assigns[:article].should_not be_new_record
  flash[:notice].should_not be_nil
  response.should redirect_to(:action => 'index')
end

Ответ 4

Как мне нравится тестировать метод обновления, просто убедитесь, что время update_at больше, чем было раньше. Когда вы это сделаете, вы можете изменить содержимое всей переменной экземпляра и по-прежнему проверить, обновлено ли все. Например:

describe "PUT 'update/:id'" do
  it "allows an article to be updated" do
    prev_updated_at = @article.updated_at
    @attr = { :title => "new title", :content => "new content" }
    put :update, :id => @article.id, :article => @attr
    @article.reload
    @article.updated_at.should != prev_updated_at 
  end
end