Ruby on rails RSpec+;工厂女工应该接受失败的培训

Ruby on rails RSpec+;工厂女工应该接受失败的培训,ruby-on-rails,rspec2,factory-bot,Ruby On Rails,Rspec2,Factory Bot,我不明白为什么RSpec测试失败。有什么建议吗?我对FactoryGirl、RSpec和TDD都是新手 控制器: 测试: 工厂: 失败: 新的错误是: Failures: 1) VendorsController POST update should update a given vendor Failure/Error: post :update, :id => @vendor.id, :vendor => FactoryGirl.attributes_for(:v

我不明白为什么RSpec测试失败。有什么建议吗?我对FactoryGirl、RSpec和TDD都是新手

控制器: 测试: 工厂: 失败: 新的错误是:

Failures:

  1) VendorsController POST update should update a given vendor
     Failure/Error: post :update, :id => @vendor.id, :vendor => FactoryGirl.attributes_for(:vendor)
       #<Vendor:0x007ff30d765900> received :update_attributes with unexpected arguments
         expected: ({:name=>"Widget Vendor"})
              got: ({"name"=>"Widget Vendor"})
     # ./app/controllers/vendors_controller.rb:33:in `update'
     # ./spec/controllers/vendors_controller_spec.rb:98:in `do_update'
     # ./spec/controllers/vendors_controller_spec.rb:108:in `block (3 levels) in <top (required)>'
故障:
1) 供应商控制器更新后应更新给定供应商
失败/错误:post:update,:id=>@vendor.id,:vendor=>FactoryGirl.attributes_for(:vendor)
#已接收:使用意外参数更新_属性
应为:({:name=>“小部件供应商”})
获取:({“名称”=>“小部件供应商”})
#./app/controllers/vendors\u controller.rb:33:in'update'
#./spec/controllers/vendors\u controller\u spec.rb:98:in'do\u update'
#./spec/controllers/vendors\u controller\u spec.rb:108:in'block(3级)in'
回答。。。? 嗯,这很有效。但是,必须有更好的方法来做到这一点:


Vendor.any\u instance.should\u receive(:update\u attributes)。with(JSON.parse(FactoryGirl.attributes)for(:Vendor.to\u JSON))and\u return(true)

我认为您需要在发布请求之前设置您的期望值;否则,当它达到您的期望时,对象已经设置好了。因此,在您的
应收到
行后移动
do\u update

it 'should update a given vendor' do
  @vendor.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))
  do_update
end

我相信你需要在发布请求之前设定你的期望;否则,当它达到您的期望时,对象已经设置好了。因此,在您的
应收到
行后移动
do\u update

it 'should update a given vendor' do
  @vendor.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))
  do_update
end

我认为你做错了

specs中的@vendor对象是控制器中的另一个对象,因此它不接收“update\u attributes”方法

您可以尝试以下方法(rspec 2.5+):

或者,您可以检查对象属性是否已更改:

expect{
  do_update
}.to change(...)

我认为你做错了

specs中的@vendor对象是控制器中的另一个对象,因此它不接收“update\u attributes”方法

您可以尝试以下方法(rspec 2.5+):

或者,您可以检查对象属性是否已更改:

expect{
  do_update
}.to change(...)

您可以在rails中使用哈希字符串化键方法:

Vendor.any_instance.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor).stringify_keys)

您可以在rails中使用哈希字符串化键方法:

Vendor.any_instance.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor).stringify_keys)

请注意:您确定@vendor.should_receive足以作为“应更新给定供应商”的断言吗?您总是调用update\u attributes-因此,即使它引发错误并且您的用户没有更新,您的测试也会成功。我想我可以在该行末尾添加
并返回(true)
。这听起来很合理(必须承认我也不是RSpec测试专家)。请注意:您确定@vendor.should_receive足以作为“应更新给定供应商”的资产吗?您总是在调用update\u attributes-因此,即使出现错误并且您的用户没有更新,您的测试也会成功。我想我可以在该行末尾添加
并返回(true)
。这听起来很合理(必须承认我也不是RSpec测试专家)。尝试过这个,但仍然会遇到同样的问题。尝试过这个,但还是有同样的问题。这就是我现在正在做的,但我遇到了问题末尾提到的问题。哦,对不起,我没有注意到。所以,也许你会使用更多的BDD样式,检查对象是否已使用expect方法更改,并且不调用should_receive?我想我现在确定的只是检查属性是否已更新,这似乎非常安全。这是我现在正在做的,但我在问题的最后遇到了上面提到的问题。哦,对不起,我没有注意到这一点。所以,也许你们会采用更多的BDD风格,用expect方法检查对象是否发生了变化,不要调用should_receive?我想我现在决定的只是检查属性是否被更新了,这看起来很安全。
Vendor.any_instance.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))
expect{
  do_update
}.to change(...)
Vendor.any_instance.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor).stringify_keys)