christofferklang
2010-Aug-09 06:29 UTC
[rspec-users] testing 404 redirects in the controller with rspec beta 19
Hello, I''m new to rails and I''m trying to wrap my heads around how to spec controllers using RSpec (using rails 3rc1 and rspec 2.0.0.beta.19). The problem I''ve run into is when I want to test that my controllers respond with a 404 for unfound records. Whenever I run the spec, the ActiveRecord::RecordNotFound exception is not caught by rails, causing the spec example to fail since the exception propagates out of the controller into the spec.>From googling around I get that rails only handles the exceptions and does a404 response when it''s run in production mode, and that you need to call rescue_action_in_public! in your example if you want this behavior for test mode. However, this does not seem to trigger rails into handling this with a redirect to 404 even though the @request.remote_addr gets set to 208.77.188.166. Do I need to set something up for rails to trigger 404 redirecting of RecordNotFound? Or is this not at all the correct way to test missing records? My full example: (using factory_girl, rspec mocks and devise) it "respons with 404 when trying to edit non-existing reads" do rescue_action_in_public! sign_in(@user) Read.should_receive(:find_by_id_and_user_id!).with(2, @user.id).and_raise(ActiveRecord::RecordNotFound) get :edit, :id => 2 response.status.should eql 404 end and the exception: 1) ReadsController resources respons with 404 for non existing reads for GET /reads/2/edit Failure/Error: get :edit, :id => 2 ActiveRecord::RecordNotFound Thanks, /Christoffer -- View this message in context: http://old.nabble.com/testing-404-redirects-in-the-controller-with-rspec-beta-19-tp29385087p29385087.html Sent from the rspec-users mailing list archive at Nabble.com. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20100808/0bcb8f14/attachment.html>
Phillip Koebbe
2010-Aug-09 10:40 UTC
[rspec-users] testing 404 redirects in the controller with rspec beta 19
On 2010-08-09 1:29 AM, christofferklang wrote:> Hello, > > I''m new to rails and I''m trying to wrap my heads around how to spec > controllers using RSpec (using rails 3rc1 and rspec 2.0.0.beta.19). > > The problem I''ve run into is when I want to test that my controllers > respond with a 404 for unfound records. Whenever I run the spec, the > ActiveRecord::RecordNotFound exception is not caught by rails, causing > the spec example to fail since the exception propagates out of the > controller into the spec. > > >From googling around I get that rails only handles the exceptions and > does a 404 response when it''s run in production mode, and that you > need to call |rescue_action_in_public!| in your example if you want > this behavior for test mode. However, this does not seem to trigger > rails into handling this with a redirect to 404 even though the > @request.remote_addr gets set to 208.77.188.166. > > Do I need to set something up for rails to trigger 404 redirecting of > RecordNotFound? Or is this not at all the correct way to test missing > records? > > My full example: (using factory_girl, rspec mocks and devise) > > it "respons with 404 when trying to edit non-existing reads" do > rescue_action_in_public! > sign_in(@user) > Read.should_receive(:find_by_id_and_user_id!).with(2, @user.id).and_raise(ActiveRecord::RecordNotFound) > > get :edit, :id => 2 > response.status.should eql 404 > end > > > and the exception: > 1) ReadsController resources respons with 404 for non existing reads for GET /reads/2/edit > Failure/Error: get :edit, :id => 2 > *ActiveRecord::RecordNotFound* > Thanks, /ChristofferThis isn''t RSpec 2 / Rails 3 specific, but here''s how I''ve come to handle this situation: I wrote a small controller plugin (I call it IdSecurity) that looks for an id parameter on all requests and queries the database looking for the matching record. If one is found, it sets an instance variable using either the class name or a custom name passed in during configuration. If it is not found, it redirects to the target of your choice, mine being an error handling route to which I pass the specific error number I want it to use (in this case, 404). For testing, all I have to do is stub the Model.find_by_id call returning nil and check that the response redirects to my error route with the error number argument. It looks something like: controller: acts_as_id_security ''/error/404'' # I haven''t managed to get it to use route helpers here :( def edit # @person will be set by IdSecurity automatically end controller spec: context ''record not found'' do it ''should redirect to error path with 404'' do Person.stub(:find_by_id).and_return(nil) get :edit, :id => ''1'' response.should redirect_to(error_path(404)) end end This allows me to test that the plugin works, use it it controllers, and forget it. I just have to remember that in every action that an id is expected, there will already be an instance variable set, but isn''t a big deal to me. Peace, Phillip
Christoffer Klang
2010-Aug-09 11:31 UTC
[rspec-users] testing 404 redirects in the controller with rspec beta 19
Ah, that looks quite interesting. I''d prefer to let rails do the 404 error handling (adding more magic to the already overwhelming amount is to much for my brain at this point ;), but if I''ll have to handle it myself this looks like a viable solution. Thanks, /Christoffer On Aug 9, 2010, at 12:40 PM, Phillip Koebbe wrote:> On 2010-08-09 1:29 AM, christofferklang wrote: >> Hello, >> >> I''m new to rails and I''m trying to wrap my heads around how to spec controllers using RSpec (using rails 3rc1 and rspec 2.0.0.beta.19). >> >> The problem I''ve run into is when I want to test that my controllers respond with a 404 for unfound records. Whenever I run the spec, the ActiveRecord::RecordNotFound exception is not caught by rails, causing the spec example to fail since the exception propagates out of the controller into the spec. >> >> >From googling around I get that rails only handles the exceptions and does a 404 response when it''s run in production mode, and that you need to call |rescue_action_in_public!| in your example if you want this behavior for test mode. However, this does not seem to trigger rails into handling this with a redirect to 404 even though the @request.remote_addr gets set to 208.77.188.166. >> >> Do I need to set something up for rails to trigger 404 redirecting of RecordNotFound? Or is this not at all the correct way to test missing records? >> >> My full example: (using factory_girl, rspec mocks and devise) >> >> it "respons with 404 when trying to edit non-existing reads" do >> rescue_action_in_public! >> sign_in(@user) >> Read.should_receive(:find_by_id_and_user_id!).with(2, @user.id).and_raise(ActiveRecord::RecordNotFound) >> >> get :edit, :id => 2 >> response.status.should eql 404 >> end >> >> >> and the exception: >> 1) ReadsController resources respons with 404 for non existing reads for GET /reads/2/edit >> Failure/Error: get :edit, :id => 2 >> *ActiveRecord::RecordNotFound* >> Thanks, /Christoffer > > This isn''t RSpec 2 / Rails 3 specific, but here''s how I''ve come to handle this situation: > > I wrote a small controller plugin (I call it IdSecurity) that looks for an id parameter on all requests and queries the database looking for the matching record. If one is found, it sets an instance variable using either the class name or a custom name passed in during configuration. If it is not found, it redirects to the target of your choice, mine being an error handling route to which I pass the specific error number I want it to use (in this case, 404). For testing, all I have to do is stub the Model.find_by_id call returning nil and check that the response redirects to my error route with the error number argument. It looks something like: > > controller: > > acts_as_id_security ''/error/404'' # I haven''t managed to get it to use route helpers here :( > > def edit > # @person will be set by IdSecurity automatically > end > > controller spec: > > context ''record not found'' do > it ''should redirect to error path with 404'' do > Person.stub(:find_by_id).and_return(nil) > get :edit, :id => ''1'' > response.should redirect_to(error_path(404)) > end > end > > This allows me to test that the plugin works, use it it controllers, and forget it. I just have to remember that in every action that an id is expected, there will already be an instance variable set, but isn''t a big deal to me. > > Peace, > Phillip > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users