How do I mock out the before :login_required method?

View: New views
9 Messages — Rating Filter:   Alert me  

How do I mock out the before :login_required method?

by Wes Shaddix :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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.[]=


_______________________________________________
rspec-users mailing list
rspec-users@...
http://rubyforge.org/mailman/listinfo/rspec-users

Re: How do I mock out the before :login_required method?

by Jarkko Laine :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


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@...
http://rubyforge.org/mailman/listinfo/rspec-users

smime.p7s (3K) Download Attachment

Re: How do I mock out the before :login_required method?

by Max Williams :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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.

Re: How do I mock out the before :login_required method?

by David Chelimsky-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Feb 13, 2008 6:52 AM, Max Williams <toastkid.williams@...> 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@...
> http://rubyforge.org/mailman/listinfo/rspec-users
>
_______________________________________________
rspec-users mailing list
rspec-users@...
http://rubyforge.org/mailman/listinfo/rspec-users

Re: How do I mock out the before :login_required method?

by Wes Shaddix :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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@...
> 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)?

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@...
http://rubyforge.org/mailman/listinfo/rspec-users

Re: How do I mock out the before :login_required method?

by David Chelimsky-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Feb 13, 2008 6:03 PM, Wes Shaddix <wshaddix@...> 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@...
> > 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@...
> http://rubyforge.org/mailman/listinfo/rspec-users
>
_______________________________________________
rspec-users mailing list
rspec-users@...
http://rubyforge.org/mailman/listinfo/rspec-users

Re: How do I mock out the before :login_required method?

by Wes Shaddix :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

David Chelimsky wrote:
On Feb 13, 2008 6:03 PM, Wes Shaddix wshaddix@... 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@...
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@...
http://rubyforge.org/mailman/listinfo/rspec-users

    
_______________________________________________
rspec-users mailing list
rspec-users@...
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)


_______________________________________________
rspec-users mailing list
rspec-users@...
http://rubyforge.org/mailman/listinfo/rspec-users

Re: How do I mock out the before :login_required method?

by David Chelimsky-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Feb 13, 2008 6:24 PM, Wes Shaddix <wshaddix@...> wrote:

>
>  David Chelimsky wrote:
>
>  On Feb 13, 2008 6:03 PM, Wes Shaddix <wshaddix@...> 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@...
> 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@...
> http://rubyforge.org/mailman/listinfo/rspec-users
>
>
>  _______________________________________________
> rspec-users mailing list
> rspec-users@...
> 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@...
> http://rubyforge.org/mailman/listinfo/rspec-users
>
_______________________________________________
rspec-users mailing list
rspec-users@...
http://rubyforge.org/mailman/listinfo/rspec-users

Re: How do I mock out the before :login_required method?

by Wes Shaddix :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

David Chelimsky wrote:

> On Feb 13, 2008 6:24 PM, Wes Shaddix <wshaddix@...> wrote:
>  
>>  David Chelimsky wrote:
>>
>>  On Feb 13, 2008 6:03 PM, Wes Shaddix <wshaddix@...> 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@...
>> 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@...
>> http://rubyforge.org/mailman/listinfo/rspec-users
>>
>>
>>  _______________________________________________
>> rspec-users mailing list
>> rspec-users@...
>> 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@...
>> http://rubyforge.org/mailman/listinfo/rspec-users
>>
>>    
> _______________________________________________
> rspec-users mailing list
> rspec-users@...
> 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
_______________________________________________
rspec-users mailing list
rspec-users@...
http://rubyforge.org/mailman/listinfo/rspec-users