Hi, I''m working on a legacy app - it was created in 1.2.5 then over time ported to 2.3. It has absolutely no tests - and I''m trying to fix that in between adding new functionality. My problem right now is that my ApplicationController is running before_filters for setting different request variables (like current location, etc.) and this messes up my tests - I can''t test responses properly (they are all redirects because ApplicationController derives from SiteController which actions implement setting variables). What''s worse I can''t test assigns hash - it doesn''t get proper values assigned. Is there a way for RSpec to skip the filters in tests? Or to stop ApplicationController to derive from SiteController? Thanks, Ignacy -- Posted via http://www.ruby-forum.com/.
> Is there a way for RSpec to skip the filters in tests? Or to stop > ApplicationController to derive from SiteController?That''s a perfect use case for mocks and/or stubs. -- Posted via http://www.ruby-forum.com/.
On 1 Jul 2009, at 12:48, Fernando Perez wrote:>> Is there a way for RSpec to skip the filters in tests? Or to stop >> ApplicationController to derive from SiteController? > That''s a perfect use case for mocks and/or stubs.Indeed. Another way to do this is to test a special subclass of SiteController, which overrides those methods that are called by the before_filters and makes them do what you want for the test (i.e. probably very little). See Michael Feathers'' excellent book ''Working Effectively with Legacy Code'' for more inspiration and ideas in wrestling with a codebase that has no existing tests. cheers, Matt Wynne http://mattwynne.net +447974 430184
Hey Ignacy, I think I''m in the minority on this one, but I tend to keep my action logic independent of filters. Doing that, my typical controller spec begins like this: require File.expand_path(File.dirname(__FILE__) + ''/../spec_helper'') require File.expand_path(File.dirname(__FILE__) + ''/../spec_helpers/ controller_behaviors'') describe SomeController do stub_all_filters! describe ... ... end The method "stub_all_filters!" is a custom rolled, per project maintained, rspec hack that rips through Rails''s internal methods to find the filters on a controller and creates a "before do ... end" that stubs each filter to "true" [1] I still use before filters because it''s a good fit for many plugins such as ssl_requirement and authentication. However 1) I don''t explicitly split up controller action behavior into filters and 2) the controller actions can depend on the filters indirectly by consuming methods like "self.current_user" I know you''re maintaining prior-written code, but I thought this would be relevant. I hope this helps more than it confuses. [1] - http://gist.github.com/142047 On Jul 1, 2009, at 4:18 AM, Ignacy Moryc wrote:> Hi, > > I''m working on a legacy app - it was created in 1.2.5 then over time > ported to 2.3. It has absolutely no tests - and I''m trying to fix that > in between adding new functionality. > > My problem right now is that my ApplicationController is running > before_filters for setting different request variables (like current > location, etc.) and this messes up my tests - I can''t test responses > properly (they are all redirects because ApplicationController derives > from SiteController which actions implement setting variables). What''s > worse I can''t test assigns hash - it doesn''t get proper values > assigned. > > Is there a way for RSpec to skip the filters in tests? Or to stop > ApplicationController to derive from SiteController? > > Thanks, > Ignacy-- Zach Moazeni http://simplechatter.com
Bleh, I forgot to mention, if you have to maintain controller action code that is dependent on instance variables set elsewhere, here is a ruby hack that will allow you to setup the context. (Please note, I recommend refactoring the code under test but I understand sometimes the preconditions of a test need to be a little....slimy. However, both the code and the spec are smelly) require File.expand_path(File.dirname(__FILE__) + ''/../spec_helper'') require File.expand_path(File.dirname(__FILE__) + ''/../spec_helpers/ controller_behaviors'') describe SomeController do stub_all_filters! describe "#foo" do def do_get get :foo end it "should do something" do controller.send(:instance_variable_set, "@bar", "here''s bar") do_get end end end class SomeController < ApplicationController def foo p "need to do something with #{@bar}" end end Here''s a gist in case the code formatting goes awry http://gist.github.com/142050 . On Jul 7, 2009, at 8:29 AM, Zach Moazeni wrote:> Hey Ignacy, > > I think I''m in the minority on this one, but I tend to keep my > action logic independent of filters. Doing that, my typical > controller spec begins like this: > > require File.expand_path(File.dirname(__FILE__) + ''/../spec_helper'') > require File.expand_path(File.dirname(__FILE__) + ''/../spec_helpers/ > controller_behaviors'') > > describe SomeController do > stub_all_filters! > > describe ... > > ... > end > > The method "stub_all_filters!" is a custom rolled, per project > maintained, rspec hack that rips through Rails''s internal methods to > find the filters on a controller and creates a "before do ... end" > that stubs each filter to "true" [1] > > I still use before filters because it''s a good fit for many plugins > such as ssl_requirement and authentication. However 1) I don''t > explicitly split up controller action behavior into filters and 2) > the controller actions can depend on the filters indirectly by > consuming methods like "self.current_user" > > I know you''re maintaining prior-written code, but I thought this > would be relevant. I hope this helps more than it confuses. > > [1] - http://gist.github.com/142047-- Zach Moazeni http://simplechatter.com