Hi folks, I''m in the process of converting a Test::Unit functional test to RSpec, but I''ve run into a slight problem. I tried looking through the documentation but I still don''t know what I missed. Thanks in advance, Blake describe VenuesController, "on update" do before(:each) do @venue = mock("venue") @venue.stub!(:new_record?).and_return(false) @venue.stub!(:to_param).and_return(''1'') controller.class.send(:define_method, :rescue_action) { |e| raise e } end it "should raise an error if record is invalid" do stub_authorized_login Venue.should_receive(:find).and_return(@venue) @venue.should_receive(:update_attributes!).with("name" => "random text").and_return(false) lambda {post :create, {:venue => @venue}}.should raise_error(ActiveRecord::RecordInvalid) end end describe VenuesController, "on create" do before(:each) do @venue = mock("venue") @venue.stub!(:new_record?).and_return(true) @venue.stub!(:to_param).and_return(''1'') Venue.stub!(:new).and_return(@venue) controller.class.send(:define_method, :rescue_action) { |e| raise e } end it "should raise an error if record is invalid" do stub_authorized_login @venue.should_receive(:save!).and_return(false) lambda {post :create, {:venue => @venue}}.should raise_error(ActiveRecord::RecordInvalid) end end 1) ''VenuesController on update should raise an error if record is invalid'' FAILED expected ActiveRecord::RecordInvalid, got # 2) ''VenuesController on create should raise an error if record is invalid'' FAILED expected ActiveRecord::RecordInvalid but nothing was raised _________________________________________________________________ Connect to the next generation of MSN Messenger? http://imagine-msn.com/messenger/launch80/default.aspx?locale=en-us&source=wlmailtagline
On 5/20/07, Blake Pettersson <blake.pettersson at hotmail.com> wrote:> > Hi folks, > > I''m in the process of converting a Test::Unit functional test to RSpec, but I''ve run into a slight problem. I tried looking through the documentation but I still don''t know what I missed. > > Thanks in advance, > Blake > > describe VenuesController, "on update" do > before(:each) do > @venue = mock("venue") > @venue.stub!(:new_record?).and_return(false) > @venue.stub!(:to_param).and_return(''1'') > controller.class.send(:define_method, :rescue_action) { |e| raise e } > end > > it "should raise an error if record is invalid" do > stub_authorized_login > Venue.should_receive(:find).and_return(@venue) > @venue.should_receive(:update_attributes!).with("name" => "random text").and_return(false) > lambda {post :create, {:venue => @venue}}.should raise_error(ActiveRecord::RecordInvalid) > end > end > > describe VenuesController, "on create" do > > before(:each) do > @venue = mock("venue") > @venue.stub!(:new_record?).and_return(true) > @venue.stub!(:to_param).and_return(''1'') > Venue.stub!(:new).and_return(@venue) > controller.class.send(:define_method, :rescue_action) { |e| raise e } > end > > it "should raise an error if record is invalid" do > stub_authorized_login > @venue.should_receive(:save!).and_return(false) > lambda {post :create, {:venue => @venue}}.should raise_error(ActiveRecord::RecordInvalid) > end > end > > 1) > ''VenuesController on update should raise an error if record is invalid'' FAILED > expected ActiveRecord::RecordInvalid, got # > > 2) > ''VenuesController on create should raise an error if record is invalid'' FAILED > expected ActiveRecord::RecordInvalid but nothing was raised >Is this shell output? Is there no backtrace? Aslak> > _________________________________________________________________ > Connect to the next generation of MSN Messenger > http://imagine-msn.com/messenger/launch80/default.aspx?locale=en-us&source=wlmailtagline > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
----------------------------------------> Date: Sun, 20 May 2007 09:04:59 -0700 > From: aslak.hellesoy at gmail.com > To: rspec-users at rubyforge.org > Subject: Re: [rspec-users] How to test for exceptions > > On 5/20/07, Blake Pettersson wrote: > > > > Hi folks, > > > > I''m in the process of converting a Test::Unit functional test to RSpec, but I''ve run into a slight problem. I tried looking through the documentation but I still don''t know what I missed. > > > > Thanks in advance, > > Blake > > > > describe VenuesController, "on update" do > > before(:each) do > > @venue = mock("venue") > > @venue.stub!(:new_record?).and_return(false) > > @venue.stub!(:to_param).and_return(''1'') > > controller.class.send(:define_method, :rescue_action) { |e| raise e } > > end > > > > it "should raise an error if record is invalid" do > > stub_authorized_login > > Venue.should_receive(:find).and_return(@venue) > > @venue.should_receive(:update_attributes!).with("name" => "random text").and_return(false) > > lambda {post :create, {:venue => @venue}}.should raise_error(ActiveRecord::RecordInvalid) > > end > > end > > > > describe VenuesController, "on create" do > > > > before(:each) do > > @venue = mock("venue") > > @venue.stub!(:new_record?).and_return(true) > > @venue.stub!(:to_param).and_return(''1'') > > Venue.stub!(:new).and_return(@venue) > > controller.class.send(:define_method, :rescue_action) { |e| raise e } > > end > > > > it "should raise an error if record is invalid" do > > stub_authorized_login > > @venue.should_receive(:save!).and_return(false) > > lambda {post :create, {:venue => @venue}}.should raise_error(ActiveRecord::RecordInvalid) > > end > > end > > > > 1) > > ''VenuesController on update should raise an error if record is invalid'' FAILED > > expected ActiveRecord::RecordInvalid, got # > > > > 2) > > ''VenuesController on create should raise an error if record is invalid'' FAILED > > expected ActiveRecord::RecordInvalid but nothing was raised > > > > Is this shell output? Is there no backtrace? > > Aslak > > > > > _________________________________________________________________ > > Connect to the next generation of MSN Messenger > > http://imagine-msn.com/messenger/launch80/default.aspx?locale=en-us&source=wlmailtagline > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-usersYes it is shell output. The full output follows: 3) ''VenuesController on create should raise an error if record is invalid'' FAILED expected ActiveRecord::RecordInvalid but nothing was raised ./spec/controllers/venues_controller_spec.rb:60: script/spec:4: line 60: lambda {post :create, {:venue => @venue}}.should raise_error(ActiveRecord::RecordInvalid) I just realised that I posted to the wrong action on the update spec. The spec still doesn''t pass though. The modified code: it "should raise an error if record is invalid" do stub_authorized_login Venue.should_receive(:find).and_return(@venue) @venue.should_receive(:update_attributes!).with("name" => "random text").and_return(false) lambda {put :update, :venue => {"name" => "random text"}}.should raise_error(ActiveRecord::RecordInvalid) end The new error: 2) ''VenuesController on update should raise an error if record is invalid'' FAILED expected ActiveRecord::RecordInvalid but nothing was raised ./spec/controllers/venues_controller_spec.rb:32: script/spec:4: line 32 is lambda {put :update, :venue => {"name" => "random text"}}.should raise_error(ActiveRecord::RecordInvalid) Regards, Blake _________________________________________________________________ Invite your mail contacts to join your friends list with Windows Live Spaces. It''s easy! http://spaces.live.com/spacesapi.aspx?wx_action=create&wx_url=/friends.aspx&mkt=en-us
Now I got confused. The error messages in your first post are not the same as in the second one: ''VenuesController on update should raise an error if record is invalid'' FAILED expected ActiveRecord::RecordInvalid, got # versus ''VenuesController on update should raise an error if record is invalid'' FAILED expected ActiveRecord::RecordInvalid but nothing was raised ./spec/controllers/venues_controller_spec.rb:32: script/spec:4: Plese post a whole new email with both code and error messages. Aslak On 5/20/07, Blake Pettersson <blake.pettersson at hotmail.com> wrote:> > ---------------------------------------- > > Date: Sun, 20 May 2007 09:04:59 -0700 > > From: aslak.hellesoy at gmail.com > > To: rspec-users at rubyforge.org > > Subject: Re: [rspec-users] How to test for exceptions > > > > On 5/20/07, Blake Pettersson wrote: > > > > > > Hi folks, > > > > > > I''m in the process of converting a Test::Unit functional test to RSpec, but I''ve run into a slight problem. I tried looking through the documentation but I still don''t know what I missed. > > > > > > Thanks in advance, > > > Blake > > > > > > describe VenuesController, "on update" do > > > before(:each) do > > > @venue = mock("venue") > > > @venue.stub!(:new_record?).and_return(false) > > > @venue.stub!(:to_param).and_return(''1'') > > > controller.class.send(:define_method, :rescue_action) { |e| raise e } > > > end > > > > > > it "should raise an error if record is invalid" do > > > stub_authorized_login > > > Venue.should_receive(:find).and_return(@venue) > > > @venue.should_receive(:update_attributes!).with("name" => "random text").and_return(false) > > > lambda {post :create, {:venue => @venue}}.should raise_error(ActiveRecord::RecordInvalid) > > > end > > > end > > > > > > describe VenuesController, "on create" do > > > > > > before(:each) do > > > @venue = mock("venue") > > > @venue.stub!(:new_record?).and_return(true) > > > @venue.stub!(:to_param).and_return(''1'') > > > Venue.stub!(:new).and_return(@venue) > > > controller.class.send(:define_method, :rescue_action) { |e| raise e } > > > end > > > > > > it "should raise an error if record is invalid" do > > > stub_authorized_login > > > @venue.should_receive(:save!).and_return(false) > > > lambda {post :create, {:venue => @venue}}.should raise_error(ActiveRecord::RecordInvalid) > > > end > > > end > > > > > > 1) > > > ''VenuesController on update should raise an error if record is invalid'' FAILED > > > expected ActiveRecord::RecordInvalid, got # > > > > > > 2) > > > ''VenuesController on create should raise an error if record is invalid'' FAILED > > > expected ActiveRecord::RecordInvalid but nothing was raised > > > > > > > Is this shell output? Is there no backtrace? > > > > Aslak > > > > > > > > _________________________________________________________________ > > > Connect to the next generation of MSN Messenger > > > http://imagine-msn.com/messenger/launch80/default.aspx?locale=en-us&source=wlmailtagline > > > _______________________________________________ > > > rspec-users mailing list > > > rspec-users at rubyforge.org > > > http://rubyforge.org/mailman/listinfo/rspec-users > > > > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > Yes it is shell output. > > The full output follows: > > 3) > ''VenuesController on create should raise an error if record is invalid'' FAILED > expected ActiveRecord::RecordInvalid but nothing was raised > ./spec/controllers/venues_controller_spec.rb:60: > script/spec:4: > > line 60: lambda {post :create, {:venue => @venue}}.should raise_error(ActiveRecord::RecordInvalid) > > I just realised that I posted to the wrong action on the update spec. The spec still doesn''t pass though. > > The modified code: > > it "should raise an error if record is invalid" do > stub_authorized_login > Venue.should_receive(:find).and_return(@venue) > @venue.should_receive(:update_attributes!).with("name" => "random text").and_return(false) > lambda {put :update, :venue => {"name" => "random text"}}.should raise_error(ActiveRecord::RecordInvalid) > end > > The new error: > > 2) > ''VenuesController on update should raise an error if record is invalid'' FAILED > expected ActiveRecord::RecordInvalid but nothing was raised > ./spec/controllers/venues_controller_spec.rb:32: > script/spec:4: > > line 32 is lambda {put :update, :venue => {"name" => "random text"}}.should raise_error(ActiveRecord::RecordInvalid) > > Regards, > Blake > > _________________________________________________________________ > Invite your mail contacts to join your friends list with Windows Live Spaces. It''s easy! > http://spaces.live.com/spacesapi.aspx?wx_action=create&wx_url=/friends.aspx&mkt=en-us > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Sorry about that, I should''ve been more clear. After sending the first message, I realised that I had sent a post to the wrong method in my spec (I sent it to create instead of update, as I meant to). Since I altered the code to reflect my true intention, so did the error message. Here''s the new (and hopefully correct) spec + error message: describe VenuesController, "on update" do before(:each) do @venue = mock("venue") @venue.stub!(:new_record?).and_return(false) @venue.stub!(:to_param).and_return(''1'') controller.class.send(:define_method, :rescue_action) { |e| raise e } end it "should raise an error if record is invalid" do stub_authorized_login Venue.should_receive(:find).and_return(@venue) @venue.should_receive(:update_attributes!).with("name" => "random text").and_return(false) lambda {put :update, :id => @venue, :venue => {"name" => "random text"}}.should raise_error(ActiveRecord::RecordInvalid) end end 2) ''VenuesController on update should raise an error if record is invalid'' FAILED expected ActiveRecord::RecordInvalid but nothing was raised ./spec/controllers/venues_controller_spec.rb:32: script/spec:4: Line 32 is in this case the last line in the spec (i.e the error assertion). Blake ----------------------------------------> Date: Sun, 20 May 2007 09:40:08 -0700 > From: aslak.hellesoy at gmail.com > To: rspec-users at rubyforge.org > Subject: Re: [rspec-users] How to test for exceptions > > Now I got confused. The error messages in your first post are not the > same as in the second one: > > ''VenuesController on update should raise an error if record is invalid'' FAILED > expected ActiveRecord::RecordInvalid, got # > > versus > > ''VenuesController on update should raise an error if record is invalid'' FAILED > expected ActiveRecord::RecordInvalid but nothing was raised > ./spec/controllers/venues_controller_spec.rb:32: > script/spec:4: > > Plese post a whole new email with both code and error messages. > > Aslak >> > The new error: > > > > 2) > > ''VenuesController on update should raise an error if record is invalid'' FAILED > > expected ActiveRecord::RecordInvalid but nothing was raised > > ./spec/controllers/venues_controller_spec.rb:32: > > script/spec:4: > > > > line 32 is lambda {put :update, :venue => {"name" => "random text"}}.should raise_error(ActiveRecord::RecordInvalid) > > > > Regards, > > Blake > > > > _________________________________________________________________ > > Invite your mail contacts to join your friends list with Windows Live Spaces. It''s easy! > > http://spaces.live.com/spacesapi.aspx?wx_action=create&wx_url=/friends.aspx&mkt=en-us > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users_________________________________________________________________ Explore the seven wonders of the world http://search.msn.com/results.aspx?q=7+wonders+world&mkt=en-US&form=QBRE
On 5/20/07, Blake Pettersson <blake.pettersson at hotmail.com> wrote:> > Sorry about that, I should''ve been more clear. After sending the first message, I realised that I had sent a post to the wrong method in my spec (I sent it to create instead of update, as I meant to). Since I altered the code to reflect my true intention, so did the error message. Here''s the new (and hopefully correct) spec + error message: > > describe VenuesController, "on update" do > > before(:each) do > @venue = mock("venue") > @venue.stub!(:new_record?).and_return(false) > @venue.stub!(:to_param).and_return(''1'') > controller.class.send(:define_method, :rescue_action) { |e| raise e } > end > > it "should raise an error if record is invalid" do > stub_authorized_login > Venue.should_receive(:find).and_return(@venue) > @venue.should_receive(:update_attributes!).with("name" => "random text").and_return(false) > lambda {put :update, :id => @venue, :venue => {"name" => "random text"}}.should raise_error(ActiveRecord::RecordInvalid) > end > end > > 2) > ''VenuesController on update should raise an error if record is invalid'' FAILED > expected ActiveRecord::RecordInvalid but nothing was raised > ./spec/controllers/venues_controller_spec.rb:32: > script/spec:4: >You generally don''t want the controller to raise an error, as it will utterly confuse your users to see a Ruby backtrace. (Scaffold-generated controllers never raise exceptions). Instead you''d want to render a special page when the update fails. Here is what I would do: describe VenuesController, "on update" do before(:each) do @venue = mock_model(Venue) Venue.should_receive(:find).and_return(@venue) end it "should re-render edit after unsuccessful update" do stub_authorized_login @venue.should_receive(:update_attributes!).and_return(false) put :update response.should render_template(''edit'') end end Aslak> Line 32 is in this case the last line in the spec (i.e the error assertion). > > Blake > > > > ---------------------------------------- > > Date: Sun, 20 May 2007 09:40:08 -0700 > > From: aslak.hellesoy at gmail.com > > To: rspec-users at rubyforge.org > > Subject: Re: [rspec-users] How to test for exceptions > > > > Now I got confused. The error messages in your first post are not the > > same as in the second one: > > > > ''VenuesController on update should raise an error if record is invalid'' FAILED > > expected ActiveRecord::RecordInvalid, got # > > > > versus > > > > ''VenuesController on update should raise an error if record is invalid'' FAILED > > expected ActiveRecord::RecordInvalid but nothing was raised > > ./spec/controllers/venues_controller_spec.rb:32: > > script/spec:4: > > > > Plese post a whole new email with both code and error messages. > > > > Aslak > > > > > > The new error: > > > > > > 2) > > > ''VenuesController on update should raise an error if record is invalid'' FAILED > > > expected ActiveRecord::RecordInvalid but nothing was raised > > > ./spec/controllers/venues_controller_spec.rb:32: > > > script/spec:4: > > > > > > line 32 is lambda {put :update, :venue => {"name" => "random text"}}.should raise_error(ActiveRecord::RecordInvalid) > > > > > > Regards, > > > Blake > > > > > > _________________________________________________________________ > > > Invite your mail contacts to join your friends list with Windows Live Spaces. It''s easy! > > > http://spaces.live.com/spacesapi.aspx?wx_action=create&wx_url=/friends.aspx&mkt=en-us > > > _______________________________________________ > > > rspec-users mailing list > > > rspec-users at rubyforge.org > > > http://rubyforge.org/mailman/listinfo/rspec-users > > > > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > _________________________________________________________________ > Explore the seven wonders of the world > http://search.msn.com/results.aspx?q=7+wonders+world&mkt=en-US&form=QBRE > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
> You generally don''t want the controller to raise an error, as it will > utterly confuse your users to see a Ruby backtrace. > (Scaffold-generated controllers never raise exceptions). Instead you''d > want to render a special page when the update fails. Here is what I > would do: > > describe VenuesController, "on update" do > before(:each) do > @venue = mock_model(Venue) > Venue.should_receive(:find).and_return(@venue) > end > > it "should re-render edit after unsuccessful update" do > stub_authorized_login > @venue.should_receive(:update_attributes!).and_return(false) > put :update > response.should render_template(''edit'') > end > end > > Aslak >I do catch the exceptions. Using the exceptional plugin, I catch any ActiveRecord::RecordInvalid exceptions on create/update and render a new/edit template. Blake _________________________________________________________________ Discover the new Windows Vista http://search.msn.com/results.aspx?q=windows+vista&mkt=en-US&form=QBRE
You want update_attributes! to raise the exception. Otherwise if you''re returning false you''ll want to be using update_attributes and if else statements. So something like it "should ..." do @venue.should_receive(:update_attributes!).with("name" => "random text").and_raise(ActiveRecord::RecordInvalid.new(mock_invalid_record)) do_update_call end it "should ..." do do_update_call response.should render_template(:edit) end This is the mock I create for invalid records. def mock_invalid_record(name = ''invalid_record'') invalid_record, errors = mock(name), mock(''errors'') invalid_record.stub!(:errors).and_return(errors) errors.stub!(:full_messages).and_return([''errors'']) invalid_record end
This was just what I needed, thanks! ----------------------------------------> Date: Sun, 20 May 2007 13:53:11 -0700 > From: dylanegan at gmail.com > To: rspec-users at rubyforge.org > Subject: Re: [rspec-users] How to test for exceptions > > You want update_attributes! to raise the exception. Otherwise if > you''re returning false you''ll want to be using update_attributes and > if else statements. > > So something like > > it "should ..." do > @venue.should_receive(:update_attributes!).with("name" => "random > text").and_raise(ActiveRecord::RecordInvalid.new(mock_invalid_record)) > do_update_call > end > > it "should ..." do > do_update_call > response.should render_template(:edit) > end > > This is the mock I create for invalid records. > > def mock_invalid_record(name = ''invalid_record'') > invalid_record, errors = mock(name), mock(''errors'') > invalid_record.stub!(:errors).and_return(errors) > errors.stub!(:full_messages).and_return([''errors'']) > invalid_record > end > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users_________________________________________________________________ Invite your mail contacts to join your friends list with Windows Live Spaces. It''s easy! http://spaces.live.com/spacesapi.aspx?wx_action=create&wx_url=/friends.aspx&mkt=en-us
On 5/20/07, Dylan Egan <dylanegan at gmail.com> wrote:> You want update_attributes! to raise the exception. Otherwise if > you''re returning false you''ll want to be using update_attributes and > if else statements. > > So something like > > it "should ..." do > @venue.should_receive(:update_attributes!).with("name" => "random > text").and_raise(ActiveRecord::RecordInvalid.new(mock_invalid_record)) > do_update_call > end > > it "should ..." do > do_update_call > response.should render_template(:edit) > end > > This is the mock I create for invalid records. > > def mock_invalid_record(name = ''invalid_record'') > invalid_record, errors = mock(name), mock(''errors'') > invalid_record.stub!(:errors).and_return(errors) > errors.stub!(:full_messages).and_return([''errors'']) > invalid_record > endDylan, I think this code is great. I''d like to recommend that this should be documented in the RSpec site somehow. If you need to test controllers that are written in the style of the AWDWR book with save! and rescue and want to test the save! part and use mocked AR models, this is definitely the way to go. Thanks for fixing me. I spent several hours on this till I came across your post. Ed -- Ed Howland http://greenprogrammer.blogspot.com "The information transmitted is intended only for the person or entity to which it is addressed and may contain proprietary, confidential and/or legally privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from all computers."