[rspec-users] Mocking Access Control

Justin Williams carpeaqua at gmail.com
Fri Jul 27 16:38:52 EDT 2007


Thanks for the help.

I think I'm getting closer.  I'm still not getting a redirect.  I
still think it's the same reason though.  I say this because when I
modify the last line of my spec to be render_template("index") instead
of redirect, it says that it renders the login template.

Am I putting the should_receive for has_role? in the wrong place?

My modified code is below.

def login
  if request.post?
  begin
    session[:user] = User.authenticate(params[:login][:email],
params[:login][:password]).id

    # Redirect the user as appropriate
    if current_user.has_role?("tutor")
      redirect_to toolkit_path
    end
  rescue
    flash[:warning] = "Your e-mail address or password is invalid."
    render :action => "login"
  end
  end
end

------

describe UsersController do
  controller_name :users

  before(:each) do
    @current_user = mock_model(User,
      :email => 'teamup at teamup.host',
      :password => 'teamup'
    )
    controller.stub!(:current_user).and_return(@current_user)
  end

  it "should login as a tutor" do
    @role = mock_model(Role, :title => 'tutor')
    @current_user.should_receive(:roles).once.and_return([@role])

    User.should_receive(:authenticate).with(@current_user.email, at current_user.password).and_return(@current_user)

    @current_user.should_receive(:has_role?).with('tutor').and_return(true)
    post :login, :login => {:email => @current_user.email, :password
=> @current_user.password}
    request.session[:user].should == @current_user.id

    should_be_logged_in

    response.should be_redirect
    response.should redirect_to(toolkit_path)
  end
end

On 7/26/07, Courtenay <court3nay at gmail.com> wrote:
> For starters, refactor your user<-->roles interaction.
>
> class User
>
>   def has_role?(name)
>     role = Role.find_by_name(name)
>     roles.include?(role)
>   end
>
> end
>
> Trust me, this will make things much easier to spec, and later, to
> scale.  Also, it keeps the DB-specific stuff ("find") in the model,
> where it belongs.
>
> It is my belief that if you see a "find" call in the controller, you
> could probably refactor it and make it easier to maintain, and just
> plain better.
>
> For example, this will only make one DB call per role check for a
> total of ~5 db calls
>
>   def has_role?(name)
>     roles.count(:conditions => { :name => name }) > 0
>   end
>
> This will make one db call to retrieve the list of role names for a
> total of 1 db call for the whole action.
>
>   def has_role?(name)
>     @role_names ||= roles.map(&:name)
>     @role_names.include?(name)
>   end
>
> So you can change the implementation without screwing round with a
> bunch of tests. In fact neither of these would require a change of
> controller specs.
>
>   @user.should_receive(:has_role?).with('tutor').and_return(true)
>
> Hope this helps :)
>
> Courtenay
>
>
> On 7/26/07, Justin Williams <carpeaqua at gmail.com> wrote:
> > I've done some more work on the specs, and it seems that my mocks
> > aren't pushing in the roles array associated with current_user.
> >
> >
> > describe UsersController do
> >   before(:each) do
> >     @user = mock_model(User,
> >       :id => 1,
> >       :email => 'teamup at teamup.host',
> >       :password => 'teamup'
> >     )
> >
> >     controller.stub!(:current_user).and_return(@user)
> >   end
> >
> >   it "should login as a tutor" do
> >     @role = mock_model(Role)
> >     @role.stub!(:title).and_return("tutor")
> >     @user.should_receive(:roles).and_return([@role])
> >     @user.stub!(:type).and_return("Tutor")
> >
> >     User.should_receive(:authenticate).with('teamup at teamup.host','teamup').and_return(@user)
> >     session[:user] = @user.id
> >     post :login, :login => {:email => "teamup at teamup.host", :password
> > => "teamup"}
> >     response.should be_success
> >     response.should redirect_to(:controller => "toolkit/overview")
> >     should_be_logged_in
> >   end
> > end
> >
> >
> > The error i receive is  'UsersController should login as a tutor'
> > FAILED expected redirect to {:controller=>"toolkit/overview"}, got no
> > redirect".  If I modify the test to be should render_template("index")
> > it will fail, saying that the template is reverting back to login.
> >
> > Any ideas on what I'm doing wrong?
> >
> > Thanks!
> >
> > - j
> >
> > On 7/24/07, Justin Williams <carpeaqua at gmail.com> wrote:
> > > On 7/24/07, David Chelimsky <dchelimsky at gmail.com> wrote:
> > >
> > > > Would you please post the code for the actions as well?
> > >
> > > def login
> > >   if request.post?
> > >   begin
> > >     session[:user] = User.authenticate(params[:login][:email],
> > > params[:login][:password]).id
> > >
> > >     if current_user.roles.include?(Role.find_by_title("employee")) or
> > > current_user.roles.include?(Role.find_by_title("administrator"))
> > >       redirect_to staff_path
> > >     elsif current_user.roles.include?(Role.find_by_title("tutor"))
> > >       redirect_to toolkit_path
> > >     elsif current_user.roles.include?(Role.find_by_title("client"))
> > >       redirect_to client_path
> > >     end
> > >    rescue
> > >      flash[:warning] = "Your e-mail address or password is invalid."
> > >      render :action => "login"
> > >    end
> > >   end
> > > end
> > >
> > >
> > > It should also be noted, I realized the specs have two different sets
> > > of credentials.  Modifying this to use a single one doesn't correct
> > > it.  I was just a bit too liberal in my cut/pasting for email.
> > >
> > > Thanks!
> > >
> > > - j
> > >
> >
> >
> > --
> > -
> > Justin Williams
> > justin at carpeaqua.com
> > work: http://www.secondgearllc.com/
> > play: http://www.carpeaqua.com
> > _______________________________________________
> > 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
>


-- 
-
Justin Williams
justin at carpeaqua.com
work: http://www.secondgearllc.com/
play: http://www.carpeaqua.com


More information about the rspec-users mailing list