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!
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
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
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
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