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

Jarkko Laine jarkko at jlaine.net
Wed Feb 13 06:49:52 EST 2008


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 


More information about the rspec-users mailing list