[rspec-users] How do I mock out the before :login_required method?

Wes Shaddix wshaddix at gmail.com
Wed Feb 13 18:03:51 EST 2008


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

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



More information about the rspec-users mailing list