如何为简单的PUT更新编写RSpec测试?

我正在努力巩固我对rails和BDD工作流程的理解,所以我想通过创建其中一个迷你博客来开始,但是使用rspec。 现在我有一个ArticlesController和Article模型,以及相关的rspec文件。 文章非常简单,只有标题:字符串和内容:文本,而ArticlesController是RESTful – 虽然我手写了MCV for Article,但它基本上和我用脚手架创建它一样。

但是,当我在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理解的问题。 如果我错了,请告诉我 – 谢谢!

你忘记了.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 

在进行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 
 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 

我喜欢测试更新方法的方法是确保updated_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