Wes Shaddix
2008-Feb-13 03:12 UTC
[rspec-users] How do I mock out the before :login_required method?
I have a GroupController class that inherits from a SecuredController which have a before filter (before_filter :login_required). This is using the restul authentication system. I want to mock out the login_required method so that my GroupController actions don''t get redirected to /sessions/new but I cant figure it out. Here is what I have so far that doesn''t work. Any help would be most appreciated. require File.dirname(__FILE__) + ''/../spec_helper'' describe GroupsController do before(:each) do # mock and stub the Group model methods @group = mock_model(Group) Group.stub!(:search_with_paginate).and_return(@group) # since this is a secured controller, we have to mock the security system too @current_user = mock_model(User, :id => 1) self.stub!(:login_required).and_return(:false) self.stub!(:current_user).and_return(@current_user) end def do_get get :index end it "should be successful" do assigns[:page] = 1 assigns[:search] = "" do_get puts response.headers response.should be_success end end The error I get is NoMethodError in ''GroupsController should be successful'' You have a nil object when you didn''t expect it! You might have expected an instance of ActiveRecord::Base. The error occurred while evaluating nil.[]=
Jarkko Laine
2008-Feb-13 11:49 UTC
[rspec-users] How do I mock out the before :login_required method?
On 13.2.2008, at 5.12, Wes Shaddix wrote:> I have a GroupController class that inherits from a SecuredController > which have a before filter (before_filter :login_required). This is > using the restul authentication system. I want to mock out the > login_required method so that my GroupController actions don''t get > redirected to /sessions/new but I cant figure it out. Here is what I > have so far that doesn''t work. Any help would be most appreciated. > > require File.dirname(__FILE__) + ''/../spec_helper'' > > describe GroupsController do > > before(:each) do > > # mock and stub the Group model methods > @group = mock_model(Group) > Group.stub!(:search_with_paginate).and_return(@group) > > > > # since this is a secured controller, we have to mock the > security system too > > @current_user = mock_model(User, :id => 1) > > self.stub!(:login_required).and_return(:false) > > self.stub!(:current_user).and_return(@current_user) > > end > > > > def do_get > > get :index > > end > > > > it "should be successful" do > > assigns[:page] = 1 > > assigns[:search] = "" > > do_get > > puts response.headers > > response.should be_success > > end > > end > > The error I get is > NoMethodError in ''GroupsController should be successful'' > You have a nil object when you didn''t expect it! > You might have expected an instance of ActiveRecord::Base. > The error occurred while evaluating nil.[]What do you expect the assigns[:... lines to do? If you mean to use them as url parameters, you have to pass them to the get method (through do_get in this case). assigns is a hash that contains all the instance variables set in the controllers. So if you say "@foo = "bar"" in your controller action, you can spec it in a controller view like this: assigns[:foo].should == "bar". However, afaik you''re not supposed to write into that hash in your controller specs. On the other hand, in the view specs you *do* need a way to set instance variables available in the views, and there you can use the assigns for that. So in a view spec corresponding to my previous example, you would want the instance variable @foo to be there so you would say "assigns[:foo] = ''bar''" in your before block. That said, I''m not a fan of stubbing the login_required method. Instead, I have created a login_as method in my spec_helper that I use whenever I want to spec something to happen when a logged in user does something (note that I also use the acl_system2 plugin for roles): def login_as(role) @role = mock_model(Role, :title => role.to_s) @current_user = mock_user({:roles => [@role]}) [:admin, :organizer, :client, :teacher].each do |r| @current_user.stub!(:has_role?).with(r).and_return(role == r ? true : false) end if defined?(controller) controller.send :current_user=, @current_user else template.stub!(:logged_in?).and_return(true) template.stub!(:current_user).and_return(@current_user) end end end This is a bit simplified but it works for me pretty well with restful_authentication. Normally you would say something like "login_as(:admin)" in a before block in controller and view specs. //jarkko -- Jarkko Laine http://jlaine.net http://dotherightthing.com http://www.railsecommerce.com http://odesign.fi -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 2417 bytes Desc: not available Url : http://rubyforge.org/pipermail/rspec-users/attachments/20080213/8470c793/attachment.bin
Max Williams
2008-Feb-13 11:52 UTC
[rspec-users] How do I mock out the before :login_required method?
I''m having a similar problem - my application controller has the UserSystem module included, and that''s where the login_required method lives. In a spec for another controller, which has before_filter :login_required, i''m trying to stub the login_required method to just return true, but i think my problem is that i''m calling it on the class instead of an instance of ApplicationController: ApplicationController.stub!("login_required").and_return(true) Looking at my log file, the :login_required filter is still failing, so it looks like my stub has missed its target. How do i call it on the actually controller? I''ve seen in another thread that "I can get the controller from my specs" but i don''t know exactly what''s meant by that. -- View this message in context: http://www.nabble.com/How-do-I-mock-out-the-before-%3Alogin_required-method--tp15448454p15456464.html Sent from the rspec-users mailing list archive at Nabble.com.
David Chelimsky
2008-Feb-13 22:08 UTC
[rspec-users] How do I mock out the before :login_required method?
On Feb 13, 2008 6:52 AM, Max Williams <toastkid.williams at gmail.com> wrote:> > I''m having a similar problem - my application controller has the UserSystem > module included, and that''s where the login_required method lives. In a > spec for another controller, which has before_filter :login_required, i''m > trying to stub the login_required method to just return true, but i think my > problem is that i''m calling it on the class instead of an instance of > ApplicationController: > > ApplicationController.stub!("login_required").and_return(true) > > Looking at my log file, the :login_required filter is still failing, so it > looks like my stub has missed its target. How do i call it on the actually > controller? I''ve seen in another thread that "I can get the controller from > my specs" but i don''t know exactly what''s meant by that.There is a method named controller that you can call to access the controller from within the spec: controller.stub!(:whatever ....) HTH, David> -- > View this message in context: http://www.nabble.com/How-do-I-mock-out-the-before-%3Alogin_required-method--tp15448454p15456464.html > Sent from the rspec-users mailing list archive at Nabble.com. > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
David Chelimsky
2008-Feb-13 23:02 UTC
[rspec-users] How do I mock out the before :login_required method?
On Feb 13, 2008 6:03 PM, Wes Shaddix <wshaddix at gmail.com> wrote:> > Jarkko Laine wrote: > > > > On 13.2.2008, at 5.12, Wes Shaddix wrote: > > > >> I have a GroupController class that inherits from a SecuredController > >> which have a before filter (before_filter :login_required). This is > >> using the restul authentication system. I want to mock out the > >> login_required method so that my GroupController actions don''t get > >> redirected to /sessions/new but I cant figure it out. Here is what I > >> have so far that doesn''t work. Any help would be most appreciated. > >> > >> require File.dirname(__FILE__) + ''/../spec_helper'' > >> > >> describe GroupsController do > >> > >> before(:each) do > >> > >> # mock and stub the Group model methods > >> @group = mock_model(Group) > >> Group.stub!(:search_with_paginate).and_return(@group) > >> > >> > >> > >> # since this is a secured controller, we have to mock the security > >> system too > >> > >> @current_user = mock_model(User, :id => 1) > >> > >> self.stub!(:login_required).and_return(:false) > >> > >> self.stub!(:current_user).and_return(@current_user) > >> > >> end > >> > >> > >> > >> def do_get > >> > >> get :index > >> > >> end > >> > >> > >> > >> it "should be successful" do > >> > >> assigns[:page] = 1 > >> > >> assigns[:search] = "" > >> > >> do_get > >> > >> puts response.headers > >> > >> response.should be_success > >> > >> end > >> > >> end > >> > >> The error I get is > >> NoMethodError in ''GroupsController should be successful'' > >> You have a nil object when you didn''t expect it! > >> You might have expected an instance of ActiveRecord::Base. > >> The error occurred while evaluating nil.[]> > > > What do you expect the assigns[:... lines to do? If you mean to use > > them as url parameters, you have to pass them to the get method > > (through do_get in this case). assigns is a hash that contains all the > > instance variables set in the controllers. So if you say "@foo > > "bar"" in your controller action, you can spec it in a controller view > > like this: assigns[:foo].should == "bar". However, afaik you''re not > > supposed to write into that hash in your controller specs. On the > > other hand, in the view specs you *do* need a way to set instance > > variables available in the views, and there you can use the assigns > > for that. So in a view spec corresponding to my previous example, you > > would want the instance variable @foo to be there so you would say > > "assigns[:foo] = ''bar''" in your before block. > > > > That said, I''m not a fan of stubbing the login_required method. > > Instead, I have created a login_as method in my spec_helper that I use > > whenever I want to spec something to happen when a logged in user does > > something (note that I also use the acl_system2 plugin for roles): > > > > def login_as(role) > > @role = mock_model(Role, :title => role.to_s) > > @current_user = mock_user({:roles => [@role]}) > > > > [:admin, :organizer, :client, :teacher].each do |r| > > @current_user.stub!(:has_role?).with(r).and_return(role == r ? > > true : false) > > end > > > > if defined?(controller) > > controller.send :current_user=, @current_user > > else > > template.stub!(:logged_in?).and_return(true) > > template.stub!(:current_user).and_return(@current_user) > > end > > end > > end > > > > This is a bit simplified but it works for me pretty well with > > restful_authentication. Normally you would say something like > > "login_as(:admin)" in a before block in controller and view specs. > > > > //jarkko > > > > -- > > Jarkko Laine > > http://jlaine.net > > http://dotherightthing.com > > http://www.railsecommerce.com > > http://odesign.fi > > > > > > ------------------------------------------------------------------------ > > > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > So, if I update my code to the following, I still get an exception, > although it is a different one. I really wish I understood how to > determine the actual call chain that is going on ... what object is nil > in this case (see error message below the code)?It should give you a file/line number, which should point you to the offensive line. FWIW, this is the same message you''d get using any framework, as it comes from Rails, not RSpec.> > require File.dirname(__FILE__) + ''/../spec_helper'' > > describe GroupsController do > > before(:each) do > # mock and stub the Group model methods > @group = mock_model(Group) > Group.stub!(:search_with_paginate).and_return(@group) > > # since this is a secured controller, we have to mock the security > system too > @current_user = mock_model(User, :id => 1) > controller.stub!(:login_required).and_return(:true) > controller.stub!(:current_user).and_return(@current_user) > end > > def do_get > get :index > end > > it "should be successful" do > do_get > puts response.headers > response.should be_success > end > > end > > Exception : RuntimeError in ''GroupsController should be successful'' > Called id for nil, which would mistakenly be 4 -- if you really wanted > the id of nil, use object_id > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Wes Shaddix
2008-Feb-13 23:03 UTC
[rspec-users] How do I mock out the before :login_required method?
Jarkko Laine wrote:> > On 13.2.2008, at 5.12, Wes Shaddix wrote: > >> I have a GroupController class that inherits from a SecuredController >> which have a before filter (before_filter :login_required). This is >> using the restul authentication system. I want to mock out the >> login_required method so that my GroupController actions don''t get >> redirected to /sessions/new but I cant figure it out. Here is what I >> have so far that doesn''t work. Any help would be most appreciated. >> >> require File.dirname(__FILE__) + ''/../spec_helper'' >> >> describe GroupsController do >> >> before(:each) do >> >> # mock and stub the Group model methods >> @group = mock_model(Group) >> Group.stub!(:search_with_paginate).and_return(@group) >> >> >> >> # since this is a secured controller, we have to mock the security >> system too >> >> @current_user = mock_model(User, :id => 1) >> >> self.stub!(:login_required).and_return(:false) >> >> self.stub!(:current_user).and_return(@current_user) >> >> end >> >> >> >> def do_get >> >> get :index >> >> end >> >> >> >> it "should be successful" do >> >> assigns[:page] = 1 >> >> assigns[:search] = "" >> >> do_get >> >> puts response.headers >> >> response.should be_success >> >> end >> >> end >> >> The error I get is >> NoMethodError in ''GroupsController should be successful'' >> You have a nil object when you didn''t expect it! >> You might have expected an instance of ActiveRecord::Base. >> The error occurred while evaluating nil.[]> > What do you expect the assigns[:... lines to do? If you mean to use > them as url parameters, you have to pass them to the get method > (through do_get in this case). assigns is a hash that contains all the > instance variables set in the controllers. So if you say "@foo = > "bar"" in your controller action, you can spec it in a controller view > like this: assigns[:foo].should == "bar". However, afaik you''re not > supposed to write into that hash in your controller specs. On the > other hand, in the view specs you *do* need a way to set instance > variables available in the views, and there you can use the assigns > for that. So in a view spec corresponding to my previous example, you > would want the instance variable @foo to be there so you would say > "assigns[:foo] = ''bar''" in your before block. > > That said, I''m not a fan of stubbing the login_required method. > Instead, I have created a login_as method in my spec_helper that I use > whenever I want to spec something to happen when a logged in user does > something (note that I also use the acl_system2 plugin for roles): > > def login_as(role) > @role = mock_model(Role, :title => role.to_s) > @current_user = mock_user({:roles => [@role]}) > > [:admin, :organizer, :client, :teacher].each do |r| > @current_user.stub!(:has_role?).with(r).and_return(role == r ? > true : false) > end > > if defined?(controller) > controller.send :current_user=, @current_user > else > template.stub!(:logged_in?).and_return(true) > template.stub!(:current_user).and_return(@current_user) > end > end > end > > This is a bit simplified but it works for me pretty well with > restful_authentication. Normally you would say something like > "login_as(:admin)" in a before block in controller and view specs. > > //jarkko > > -- > Jarkko Laine > http://jlaine.net > http://dotherightthing.com > http://www.railsecommerce.com > http://odesign.fi > > > ------------------------------------------------------------------------ > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-usersSo, if I update my code to the following, I still get an exception, although it is a different one. I really wish I understood how to determine the actual call chain that is going on ... what object is nil in this case (see error message below the code)? require File.dirname(__FILE__) + ''/../spec_helper'' describe GroupsController do before(:each) do # mock and stub the Group model methods @group = mock_model(Group) Group.stub!(:search_with_paginate).and_return(@group) # since this is a secured controller, we have to mock the security system too @current_user = mock_model(User, :id => 1) controller.stub!(:login_required).and_return(:true) controller.stub!(:current_user).and_return(@current_user) end def do_get get :index end it "should be successful" do do_get puts response.headers response.should be_success end end Exception : RuntimeError in ''GroupsController should be successful'' Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
David Chelimsky
2008-Feb-13 23:22 UTC
[rspec-users] How do I mock out the before :login_required method?
On Feb 13, 2008 6:24 PM, Wes Shaddix <wshaddix at gmail.com> wrote:> > David Chelimsky wrote: > > On Feb 13, 2008 6:03 PM, Wes Shaddix <wshaddix at gmail.com> wrote: > > > Jarkko Laine wrote: > > > On 13.2.2008, at 5.12, Wes Shaddix wrote: > > > > I have a GroupController class that inherits from a SecuredController > which have a before filter (before_filter :login_required). This is > using the restul authentication system. I want to mock out the > login_required method so that my GroupController actions don''t get > redirected to /sessions/new but I cant figure it out. Here is what I > have so far that doesn''t work. Any help would be most appreciated. > > require File.dirname(__FILE__) + ''/../spec_helper'' > > describe GroupsController do > > before(:each) do > > # mock and stub the Group model methods > @group = mock_model(Group) > Group.stub!(:search_with_paginate).and_return(@group) > > > > # since this is a secured controller, we have to mock the security > system too > > @current_user = mock_model(User, :id => 1) > > self.stub!(:login_required).and_return(:false) > > self.stub!(:current_user).and_return(@current_user) > > end > > > > def do_get > > get :index > > end > > > > it "should be successful" do > > assigns[:page] = 1 > > assigns[:search] = "" > > do_get > > puts response.headers > > response.should be_success > > end > > end > > The error I get is > NoMethodError in ''GroupsController should be successful'' > You have a nil object when you didn''t expect it! > You might have expected an instance of ActiveRecord::Base. > The error occurred while evaluating nil.[]> > What do you expect the assigns[:... lines to do? If you mean to use > them as url parameters, you have to pass them to the get method > (through do_get in this case). assigns is a hash that contains all the > instance variables set in the controllers. So if you say "@foo > "bar"" in your controller action, you can spec it in a controller view > like this: assigns[:foo].should == "bar". However, afaik you''re not > supposed to write into that hash in your controller specs. On the > other hand, in the view specs you *do* need a way to set instance > variables available in the views, and there you can use the assigns > for that. So in a view spec corresponding to my previous example, you > would want the instance variable @foo to be there so you would say > "assigns[:foo] = ''bar''" in your before block. > > That said, I''m not a fan of stubbing the login_required method. > Instead, I have created a login_as method in my spec_helper that I use > whenever I want to spec something to happen when a logged in user does > something (note that I also use the acl_system2 plugin for roles): > > def login_as(role) > @role = mock_model(Role, :title => role.to_s) > @current_user = mock_user({:roles => [@role]}) > > [:admin, :organizer, :client, :teacher].each do |r| > @current_user.stub!(:has_role?).with(r).and_return(role == r ? > true : false) > end > > if defined?(controller) > controller.send :current_user=, @current_user > else > template.stub!(:logged_in?).and_return(true) > template.stub!(:current_user).and_return(@current_user) > end > end > end > > This is a bit simplified but it works for me pretty well with > restful_authentication. Normally you would say something like > "login_as(:admin)" in a before block in controller and view specs. > > //jarkko > > -- > Jarkko Laine > http://jlaine.net > http://dotherightthing.com > http://www.railsecommerce.com > http://odesign.fi > > > ------------------------------------------------------------------------ > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users > > So, if I update my code to the following, I still get an exception, > although it is a different one. I really wish I understood how to > determine the actual call chain that is going on ... what object is nil > in this case (see error message below the code)? > > It should give you a file/line number, which should point you to the > offensive line. FWIW, this is the same message you''d get using any > framework, as it comes from Rails, not RSpec. > > > > require File.dirname(__FILE__) + ''/../spec_helper'' > > describe GroupsController do > > before(:each) do > # mock and stub the Group model methods > @group = mock_model(Group) > Group.stub!(:search_with_paginate).and_return(@group) > > # since this is a secured controller, we have to mock the security > system too > @current_user = mock_model(User, :id => 1) > controller.stub!(:login_required).and_return(:true) > controller.stub!(:current_user).and_return(@current_user) > end > > def do_get > get :index > end > > it "should be successful" do > do_get > puts response.headers > response.should be_success > end > > end > > Exception : RuntimeError in ''GroupsController should be successful'' > Called id for nil, which would mistakenly be 4 -- if you really wanted > the id of nil, use object_id > > > _______________________________________________ > 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 > > Gotcha ... this is the offending line in my GroupsController > > @groups = Group.search_with_paginate(params[:page], params[:search], > @current_user.id)This is referencing the @current_user instance variable here, not the current_user method.> > Which I''m sure is the @current_user.id. Where I''m confused is that I > thought the following line in my GroupsController_spec would intercept this > call and return the mock current_user instance: > > @current_user = mock_model(User, :id => 1) > controller.stub!(:login_required).and_return(:true) > controller.stub!(:current_user).and_return(@current_user)And this is stubbing the current_user method. So you want to change the line in the controller to: @groups = Group.search_with_paginate(params[:page], params[:search], current_user.id) Cheers, David> > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Wes Shaddix
2008-Feb-13 23:24 UTC
[rspec-users] How do I mock out the before :login_required method?
David Chelimsky wrote:> On Feb 13, 2008 6:03 PM, Wes Shaddix <wshaddix at gmail.com> wrote: > >> Jarkko Laine wrote: >> >>> On 13.2.2008, at 5.12, Wes Shaddix wrote: >>> >>> >>>> I have a GroupController class that inherits from a SecuredController >>>> which have a before filter (before_filter :login_required). This is >>>> using the restul authentication system. I want to mock out the >>>> login_required method so that my GroupController actions don''t get >>>> redirected to /sessions/new but I cant figure it out. Here is what I >>>> have so far that doesn''t work. Any help would be most appreciated. >>>> >>>> require File.dirname(__FILE__) + ''/../spec_helper'' >>>> >>>> describe GroupsController do >>>> >>>> before(:each) do >>>> >>>> # mock and stub the Group model methods >>>> @group = mock_model(Group) >>>> Group.stub!(:search_with_paginate).and_return(@group) >>>> >>>> >>>> >>>> # since this is a secured controller, we have to mock the security >>>> system too >>>> >>>> @current_user = mock_model(User, :id => 1) >>>> >>>> self.stub!(:login_required).and_return(:false) >>>> >>>> self.stub!(:current_user).and_return(@current_user) >>>> >>>> end >>>> >>>> >>>> >>>> def do_get >>>> >>>> get :index >>>> >>>> end >>>> >>>> >>>> >>>> it "should be successful" do >>>> >>>> assigns[:page] = 1 >>>> >>>> assigns[:search] = "" >>>> >>>> do_get >>>> >>>> puts response.headers >>>> >>>> response.should be_success >>>> >>>> end >>>> >>>> end >>>> >>>> The error I get is >>>> NoMethodError in ''GroupsController should be successful'' >>>> You have a nil object when you didn''t expect it! >>>> You might have expected an instance of ActiveRecord::Base. >>>> The error occurred while evaluating nil.[]>>>> >>> What do you expect the assigns[:... lines to do? If you mean to use >>> them as url parameters, you have to pass them to the get method >>> (through do_get in this case). assigns is a hash that contains all the >>> instance variables set in the controllers. So if you say "@foo >>> "bar"" in your controller action, you can spec it in a controller view >>> like this: assigns[:foo].should == "bar". However, afaik you''re not >>> supposed to write into that hash in your controller specs. On the >>> other hand, in the view specs you *do* need a way to set instance >>> variables available in the views, and there you can use the assigns >>> for that. So in a view spec corresponding to my previous example, you >>> would want the instance variable @foo to be there so you would say >>> "assigns[:foo] = ''bar''" in your before block. >>> >>> That said, I''m not a fan of stubbing the login_required method. >>> Instead, I have created a login_as method in my spec_helper that I use >>> whenever I want to spec something to happen when a logged in user does >>> something (note that I also use the acl_system2 plugin for roles): >>> >>> def login_as(role) >>> @role = mock_model(Role, :title => role.to_s) >>> @current_user = mock_user({:roles => [@role]}) >>> >>> [:admin, :organizer, :client, :teacher].each do |r| >>> @current_user.stub!(:has_role?).with(r).and_return(role == r ? >>> true : false) >>> end >>> >>> if defined?(controller) >>> controller.send :current_user=, @current_user >>> else >>> template.stub!(:logged_in?).and_return(true) >>> template.stub!(:current_user).and_return(@current_user) >>> end >>> end >>> end >>> >>> This is a bit simplified but it works for me pretty well with >>> restful_authentication. Normally you would say something like >>> "login_as(:admin)" in a before block in controller and view specs. >>> >>> //jarkko >>> >>> -- >>> Jarkko Laine >>> http://jlaine.net >>> http://dotherightthing.com >>> http://www.railsecommerce.com >>> http://odesign.fi >>> >>> >>> ------------------------------------------------------------------------ >>> >>> _______________________________________________ >>> rspec-users mailing list >>> rspec-users at rubyforge.org >>> http://rubyforge.org/mailman/listinfo/rspec-users >>> >> So, if I update my code to the following, I still get an exception, >> although it is a different one. I really wish I understood how to >> determine the actual call chain that is going on ... what object is nil >> in this case (see error message below the code)? >> > > It should give you a file/line number, which should point you to the > offensive line. FWIW, this is the same message you''d get using any > framework, as it comes from Rails, not RSpec. > > >> require File.dirname(__FILE__) + ''/../spec_helper'' >> >> describe GroupsController do >> >> before(:each) do >> # mock and stub the Group model methods >> @group = mock_model(Group) >> Group.stub!(:search_with_paginate).and_return(@group) >> >> # since this is a secured controller, we have to mock the security >> system too >> @current_user = mock_model(User, :id => 1) >> controller.stub!(:login_required).and_return(:true) >> controller.stub!(:current_user).and_return(@current_user) >> end >> >> def do_get >> get :index >> end >> >> it "should be successful" do >> do_get >> puts response.headers >> response.should be_success >> end >> >> end >> >> Exception : RuntimeError in ''GroupsController should be successful'' >> Called id for nil, which would mistakenly be 4 -- if you really wanted >> the id of nil, use object_id >> >> >> _______________________________________________ >> 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 >Gotcha ... this is the offending line in my GroupsController @groups = Group.search_with_paginate(params[:page], params[:search], @current_user.id) Which I''m sure is the @current_user.id. Where I''m confused is that I thought the following line in my GroupsController_spec would intercept this call and return the mock current_user instance: @current_user = mock_model(User, :id => 1) controller.stub!(:login_required).and_return(:true) controller.stub!(:current_user).and_return(@current_user) -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/rspec-users/attachments/20080213/3c14965a/attachment.html
Wes Shaddix
2008-Feb-13 23:32 UTC
[rspec-users] How do I mock out the before :login_required method?
David Chelimsky wrote:> On Feb 13, 2008 6:24 PM, Wes Shaddix <wshaddix at gmail.com> wrote: > >> David Chelimsky wrote: >> >> On Feb 13, 2008 6:03 PM, Wes Shaddix <wshaddix at gmail.com> wrote: >> >> >> Jarkko Laine wrote: >> >> >> On 13.2.2008, at 5.12, Wes Shaddix wrote: >> >> >> >> I have a GroupController class that inherits from a SecuredController >> which have a before filter (before_filter :login_required). This is >> using the restul authentication system. I want to mock out the >> login_required method so that my GroupController actions don''t get >> redirected to /sessions/new but I cant figure it out. Here is what I >> have so far that doesn''t work. Any help would be most appreciated. >> >> require File.dirname(__FILE__) + ''/../spec_helper'' >> >> describe GroupsController do >> >> before(:each) do >> >> # mock and stub the Group model methods >> @group = mock_model(Group) >> Group.stub!(:search_with_paginate).and_return(@group) >> >> >> >> # since this is a secured controller, we have to mock the security >> system too >> >> @current_user = mock_model(User, :id => 1) >> >> self.stub!(:login_required).and_return(:false) >> >> self.stub!(:current_user).and_return(@current_user) >> >> end >> >> >> >> def do_get >> >> get :index >> >> end >> >> >> >> it "should be successful" do >> >> assigns[:page] = 1 >> >> assigns[:search] = "" >> >> do_get >> >> puts response.headers >> >> response.should be_success >> >> end >> >> end >> >> The error I get is >> NoMethodError in ''GroupsController should be successful'' >> You have a nil object when you didn''t expect it! >> You might have expected an instance of ActiveRecord::Base. >> The error occurred while evaluating nil.[]>> >> What do you expect the assigns[:... lines to do? If you mean to use >> them as url parameters, you have to pass them to the get method >> (through do_get in this case). assigns is a hash that contains all the >> instance variables set in the controllers. So if you say "@foo >> "bar"" in your controller action, you can spec it in a controller view >> like this: assigns[:foo].should == "bar". However, afaik you''re not >> supposed to write into that hash in your controller specs. On the >> other hand, in the view specs you *do* need a way to set instance >> variables available in the views, and there you can use the assigns >> for that. So in a view spec corresponding to my previous example, you >> would want the instance variable @foo to be there so you would say >> "assigns[:foo] = ''bar''" in your before block. >> >> That said, I''m not a fan of stubbing the login_required method. >> Instead, I have created a login_as method in my spec_helper that I use >> whenever I want to spec something to happen when a logged in user does >> something (note that I also use the acl_system2 plugin for roles): >> >> def login_as(role) >> @role = mock_model(Role, :title => role.to_s) >> @current_user = mock_user({:roles => [@role]}) >> >> [:admin, :organizer, :client, :teacher].each do |r| >> @current_user.stub!(:has_role?).with(r).and_return(role == r ? >> true : false) >> end >> >> if defined?(controller) >> controller.send :current_user=, @current_user >> else >> template.stub!(:logged_in?).and_return(true) >> template.stub!(:current_user).and_return(@current_user) >> end >> end >> end >> >> This is a bit simplified but it works for me pretty well with >> restful_authentication. Normally you would say something like >> "login_as(:admin)" in a before block in controller and view specs. >> >> //jarkko >> >> -- >> Jarkko Laine >> http://jlaine.net >> http://dotherightthing.com >> http://www.railsecommerce.com >> http://odesign.fi >> >> >> ------------------------------------------------------------------------ >> >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users >> >> So, if I update my code to the following, I still get an exception, >> although it is a different one. I really wish I understood how to >> determine the actual call chain that is going on ... what object is nil >> in this case (see error message below the code)? >> >> It should give you a file/line number, which should point you to the >> offensive line. FWIW, this is the same message you''d get using any >> framework, as it comes from Rails, not RSpec. >> >> >> >> require File.dirname(__FILE__) + ''/../spec_helper'' >> >> describe GroupsController do >> >> before(:each) do >> # mock and stub the Group model methods >> @group = mock_model(Group) >> Group.stub!(:search_with_paginate).and_return(@group) >> >> # since this is a secured controller, we have to mock the security >> system too >> @current_user = mock_model(User, :id => 1) >> controller.stub!(:login_required).and_return(:true) >> controller.stub!(:current_user).and_return(@current_user) >> end >> >> def do_get >> get :index >> end >> >> it "should be successful" do >> do_get >> puts response.headers >> response.should be_success >> end >> >> end >> >> Exception : RuntimeError in ''GroupsController should be successful'' >> Called id for nil, which would mistakenly be 4 -- if you really wanted >> the id of nil, use object_id >> >> >> _______________________________________________ >> 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 >> >> Gotcha ... this is the offending line in my GroupsController >> >> @groups = Group.search_with_paginate(params[:page], params[:search], >> @current_user.id) >> > > > This is referencing the @current_user instance variable here, not the > current_user method. > > >> Which I''m sure is the @current_user.id. Where I''m confused is that I >> thought the following line in my GroupsController_spec would intercept this >> call and return the mock current_user instance: >> >> @current_user = mock_model(User, :id => 1) >> controller.stub!(:login_required).and_return(:true) >> controller.stub!(:current_user).and_return(@current_user) >> > > > And this is stubbing the current_user method. > > So you want to change the line in the controller to: > > @groups = Group.search_with_paginate(params[:page], params[:search], > current_user.id) > > Cheers, > David > > >> _______________________________________________ >> 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 >Well, it seems so clear when you write the code for me :) Thank you for your time and help. Wes