Ronze
Ronze

Reputation: 1574

Testing @current_user method using RSpec

I've been trying to do this for a couple of days now, but I can't figure it out. I have the following code in my controller:

@some_object = @current_user.some_method

In my spec, I want to attach a should_receive hook on that method, but I can't make it work. I've tried all of these, but none of them work:

assigns[:current_user].should_receive(:some_method).at_least(:once) # expected 1, got 0
User.should_receive(:some_method).at_least(:once) # expected 1, got 0

How is the correct way of testing this? I'm running this in my spec, and login is working:

setup :activate_authlogic
...
UserSession.create(users(:rune))

Thanks!

Upvotes: 3

Views: 4876

Answers (2)

Sankalp Singha
Sankalp Singha

Reputation: 4546

You can’t call something like in the controllers:

expect(current_user).to be_present
expect(user_signed_in?).to be_true

So to do so, you can do this :

module ControllerMacros
  def current_user
    user_session_info = response.request.env['rack.session']['warden.user.user.key']
    if user_session_info
      user_id = user_session_info[0][0]
      User.find(user_id)
    else
      nil
    end
  end

  def user_signed_in?
    !!current_user
  end
end

You can either include the ControllerMacros in the top of the controller spec or include it in the spec_helper.rb like so :

RSpec.configure do |config|
  config.include ControllerMacros, type: :controller
end

Upvotes: 2

Michelle Tilley
Michelle Tilley

Reputation: 159135

One example comes from the Ruby on Rails Tutorial. Rather than setting and reading @current_user directly, it defines two helper methods:

def current_user=(user)
  @current_user = user
end

def current_user
  @current_user
end

Later, they access this method in the tests using the controller method:

def test_sign_in(user)
  controller.current_user = user
end

Using this methodology, you should be able to use

controller.current_user.should_receive(:some_method).at_least(:once)

Upvotes: 5

Related Questions