Gordon
2011-Oct-25 06:56 UTC
[rspec-users] upgraded to rails 3.1.0 and found that string value of id has to be used instead of the integer value.
My advance apologies if the title/subject is not too descriptive. Pre: I have just upgraded from rails 3.0.9 to rails 3.1.0 Before the upgrade, running ''rake spec'' sees all my specs pass. After the upgrade, I seem to encounter some errors: -------------- Error extracts start ------------------------------- controller_spec.rb ./spec/controllers/parts_controller_spec.rb ............................FFF Failures: 1) PartsController saves updates to an existing part object successfully by finding the existing part and returning it for update Failure/Error: put :update, :id => "1", :part => { <Part(id: integer, title: string, description: text, created_by: integer, updated_by: integer, created_at: datetime, updated_at: datetime) (class)> received :find with unexpected arguments expected: (1) got: ("1") # ./app/controllers/parts_controller.rb:131:in `check_authorisation'' # ./spec/controllers/parts_controller_spec.rb:74:in `block (3 levels) in <top (required)>'' 2) PartsController saves updates to an existing part object successfully does its job in saving the update Failure/Error: put :update, :id => 1, :part => { <Part(id: integer, title: string, description: text, created_by: integer, updated_by: integer, created_at: datetime, updated_at: datetime) (class)> received :find with unexpected arguments expected: (1) got: ("1") # ./app/controllers/parts_controller.rb:131:in `check_authorisation'' # ./spec/controllers/parts_controller_spec.rb:81:in `block (3 levels) in <top (required)>'' 3) PartsController saves updates to an existing part object successfully communicates the successful update via the flash Failure/Error: put :update, :id => 1, :part => {''title'' => ''Brake pads''} <Part(id: integer, title: string, description: text, created_by: integer, updated_by: integer, created_at: datetime, updated_at: datetime) (class)> received :find with unexpected arguments expected: (1) got: ("1") # ./app/controllers/parts_controller.rb:131:in `check_authorisation'' # ./spec/controllers/parts_controller_spec.rb:87:in `block (3 levels) in <top (required)>'' Finished in 8.02 seconds 31 examples, 3 failures Failed examples: rspec ./spec/controllers/parts_controller_spec.rb:72 # PartsController saves updates to an existing part object successfully by finding the existing part and returning it for update rspec ./spec/controllers/parts_controller_spec.rb:79 # PartsController saves updates to an existing part object successfully does its job in saving the update rspec ./spec/controllers/parts_controller_spec.rb:86 # PartsController saves updates to an existing part object successfully communicates the successful update via the flash rake aborted! -------------- Error extracts end ------------------------------- My parts'' controller spec reads: ------------ /spec/controllers/parts_controller_spec.rb start ------------- 63 context ''saves updates to an existing part object successfully'' do 64 @new_title = ''Brake pads'' 65 66 before(:each) do 67 @part = mock_model(Part, :update_attributes! => true, :created_by => @user.id) 68 Part.stub!(''check_authorisation'').and_return(true) 69 Part.stub!(:find).with(1).and_return(@part) 70 end 71 72 it ''by finding the existing part and returning it for update'' do 73 Part.should_receive(:find).with(1).and_return(@part) 74 put :update, :id => "1", :part => { 75 ''title'' => @new_title 76 } 77 end 78 79 it ''does its job in saving the update'' do 80 @part.should_receive(:update_attributes!).and_return(true) 81 put :update, :id => 1, :part => { 82 ''title'' => @new_title 83 } 84 end 85 86 it ''communicates the successful update via the flash'' do 87 put :update, :id => 1, :part => {''title'' => ''Brake pads''} 88 flash[:notice].should eql(''Part was successfully updated.'') 89 end 90 end ------------ /spec/controllers/parts_controller_spec.rb end ------------- What I did: By changing the argument value from 1 to ''1'' in the lines that deal with the a) stubbing of the find method (with a value of 1) b) should_receive test Here''s how the lines look like after the change: 69 Part.stub!(:find).with(''1'').and_return(@part) 73 Part.should_receive(:find).with(''1'').and_return(@part) The result is that all specs pass. --------- Extract of run - start ---------------------- 192-168-1-2:script anexiole$ rake spec:controllers (in /Users/ct9a/projects/try_rails) /usr/local/rvm/rubies/ruby-1.9.2-p290/bin/ruby -S rspec ./spec/ controllers/application_controller_spec.rb ./spec/controllers/ brands_controller_spec.rb ./spec/controllers/home_controller_spec.rb ./ spec/controllers/parts_controller_spec.rb ............................... Finished in 8.49 seconds 31 examples, 0 failures --------- Extract of run - end ---------------------- I can''t think of a good reason of why putting the quotes worked after the upgrade to rails 3.1? It''s worked fine all this while circa rails 3.1 Why should I have to pass a string of ''1'' instead of using the integer value, 1 of the id to the stubbing definition for the find method (As argument) and the expected id value in the should_receive test? Would like to hear some thoughts on this behaviour. Thank you Gorodn Yeong
David Chelimsky
2011-Oct-25 12:54 UTC
[rspec-users] upgraded to rails 3.1.0 and found that string value of id has to be used instead of the integer value.
On Oct 25, 2011, at 1:56 AM, Gordon wrote:> My advance apologies if the title/subject is not too descriptive. > > > Pre: I have just upgraded from rails 3.0.9 to rails 3.1.0 > > Before the upgrade, running ''rake spec'' sees all my specs pass. > > After the upgrade, I seem to encounter some errors: > -------------- Error extracts start ------------------------------- > controller_spec.rb ./spec/controllers/parts_controller_spec.rb > ............................FFF > > Failures: > > 1) PartsController saves updates to an existing part object > successfully by finding the existing part and returning it for update > Failure/Error: put :update, :id => "1", :part => { > <Part(id: integer, title: string, description: text, > created_by: integer, updated_by: integer, created_at: datetime, > updated_at: datetime) (class)> received :find with unexpected > arguments > expected: (1) > got: ("1") > # ./app/controllers/parts_controller.rb:131:in > `check_authorisation'' > # ./spec/controllers/parts_controller_spec.rb:74:in `block (3 > levels) in <top (required)>''<snip/>> I can''t think of a good reason of why putting the quotes worked after > the upgrade to rails 3.1? It''s worked fine all this while circa rails > 3.1I can, but not because it''s an rspec issue. I just happened to submit the patch to Rails that made this change. [1] The problem is that Rails functional tests, which power rspec controller specs, don''t go through rack. This means that you used to be able to do this in a controller spec: it "does one thing if :some_number is > 5" do get :some_action, :some_number = 6 end And this in the controller: def some_action if params[:some_number] > 5 do_this else do_that end end And the spec would pass, but it would fail when running through rack, as it does when you run a server. That''s because all parameters are ''to_param''d before they make it to a controller when running through rack, but they weren''t getting the same treatment in Rails functional tests. This was true whether you were using rspec, minitest, test/unit, etc, and was happening because the Rails test framework was letting Fixnums in the specs make it directly to the controllers. So the upside of this change is that we decrease the likelihood of false positives. The downside is that you have to change stubs and message expectations that are constrained on non-strings to expect strings. The upside of the downside is that your specs are now telling the truth, and are correctly aligned with the reality of the running application. HTH, David [1] https://github.com/rails/rails/pull/1203> Why should I have to pass a string of ''1'' instead of using the integer > value, 1 of the id to the stubbing definition for the find method (As > argument) and the expected id value in the should_receive test? > > Would like to hear some thoughts on this behaviour. > > Thank you > > > Gorodn Yeong