webentwicklung-frage-antwort-db.com.de

Wie schreibe ich einen RSpec-Test für ein einfaches PUT-Update?

Ich versuche, mein Verständnis von Rails und des BDD-Workflows zu festigen. Deshalb wollte ich klein damit anfangen, einen dieser Mini-Blogs zu erstellen, allerdings mit rspec. Im Moment habe ich ein ArticlesController- und Article-Modell sowie zugehörige rspec-Dateien. Der Artikel ist sehr einfach und hat nur Titel: Zeichenfolge und Inhalt: Text. Der ArticlesController ist RESTful - obwohl ich den MCV für Artikel von Hand geschrieben habe, ist es im Grunde dasselbe, als würde ich ein Gerüst verwenden, um ihn zu erstellen.

Ich weiß jedoch nicht wirklich, was ich mache, wenn es darum geht, einen Test für das PUT-Update in rspec zu schreiben. Ich verwende Factory Girl, um das Artikelobjekt zu erstellen, und mein Code sieht bisher so aus:

#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

Ich bekomme jedoch immer:

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

Was mache ich falsch? Und benutze ich die richtigen Werkzeuge? Wenn ich meinen Testserver betreibe, Neu, Bearbeiten, Zerstöre alle Arbeiten in der von mir erwarteten Weise. Ich vermute, dies ist ein Problem mit meinem Verständnis von RSpec. Lass es mich wissen, wenn ich falsch liege - danke!

31
oort

Sie haben vergessen, .reload Ihren @article zu ändern, und bei update-Aktion führt Ihre Antwort höchstwahrscheinlich eine Umleitung durch, also

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
55

Wenn Sie einen PUT :update ausführen, müssen Sie daran denken, dass Sie ein vorhandenes Modell bearbeiten, das Sie in der put aufrufen müssen. Übergeben Sie einfach Ihren @article und aktualisieren Sie die Attribute wie folgt.

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
6
nmott
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
1
Sandip Ransing

Ich möchte die Aktualisierungsmethode gerne testen, indem Sie einfach sicherstellen, dass die Aktualisierungszeit länger ist als zuvor. Wenn Sie dies tun, können Sie den Inhalt der gesamten Instanzvariablen ändern und trotzdem überprüfen, ob alles aktualisiert wurde. Zum Beispiel:

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
0
David Hahn