Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/53.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何为简单的PUT更新编写RSpec测试?_Ruby On Rails_Rspec_Factory Bot - Fatal编程技术网

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

Ruby on rails 如何为简单的PUT更新编写RSpec测试?,ruby-on-rails,rspec,factory-bot,Ruby On Rails,Rspec,Factory Bot,我试图巩固我对rails和BDD工作流程的理解,所以我想从创建一个小型博客开始,但要使用rspec。现在我有一个ArticlesController和文章模型,以及相关的rspec文件。这篇文章非常简单,只有标题:字符串和内容:文本,ArticlesController是RESTful的——虽然我为这篇文章手工编写了MCV,但它基本上和我使用脚手架创建它一样 然而,当涉及到在rspec中为PUT更新编写测试时,我真的不知道我在做什么。我正在使用Factory Girl创建article对象,到目

我试图巩固我对rails和BDD工作流程的理解,所以我想从创建一个小型博客开始,但要使用rspec。现在我有一个ArticlesController和文章模型,以及相关的rspec文件。这篇文章非常简单,只有标题:字符串和内容:文本,ArticlesController是RESTful的——虽然我为这篇文章手工编写了MCV,但它基本上和我使用脚手架创建它一样

然而,当涉及到在rspec中为PUT更新编写测试时,我真的不知道我在做什么。我正在使用Factory Girl创建article对象,到目前为止,我的代码如下所示:

#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

我做错了什么?我是否使用了正确的工具?当我运行我的测试服务器时,新建、编辑、销毁所有我期望的工作,所以我猜这是我理解RSpec的一个问题。如果我错了,请告诉我-谢谢

执行
PUT:update
时,请记住您正在编辑现有模型,需要在
PUT
中调用该模型。只需传递您的
@文章
,并按如下方式更新属性

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

您忘记了
。重新加载
您的
@文章
,并且在
更新
操作中,您的响应很可能执行重定向,因此

rspec2:

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
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
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 { response.should redirect_to(@article) }
  it { @article.title.should eql attr[:title] }
  it { @article.content.should eql attr[:content] }
end
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

我喜欢测试update方法的方法是确保当时更新的_比以前更大。执行此操作时,您可以更改整个实例变量的内容,并且仍然可以检查是否所有内容都已更新。例如:

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

你的控制器和模型是什么样子的?另外,新的matcher语法将有@article.title.eq@attr[:title]应该祝福你美丽的小灵魂。我真是束手无策。更新的语法应该是:
expect(@article.title)。为了均衡@attr[:title]
。我忘记了更新后的
重新加载
。这个答案救了我。非常感谢。从中,我了解到在规范中使用实例方法不是一个好主意。如果在这里看到一个没有实例方法的示例,那就太好了。您的代码似乎断言时间与您描述的相同,而不是不同。@默认情况下,更新是put请求,但您始终可以覆盖它。