RSpec: how to stub inherited method current_user (w/o Devise)?

Also works

user = create(:user) #FactoryBot

allow(controller).to receive(:current_user).and_return(user)

I run into the same problem with a legacy Rails 4 app and based my solution on this test case of Rspec Views.

First define a helper that will define the missing helper method in the controller instance

# /spec/support/concerns/view_helper.rb
module ViewHelper
  def include_current_user_helper(&block)
    controller.singleton_class.class_eval do
      define_method :current_user, &block
      helper_method :current_user
    end
  end
end

Then configure Rspec to include it in all the view helpers

# spec/rails_helper.rb
# ...
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

RSpec.configure do |config|
  # ...
  config.include ViewHelper, type: :view
end

And in the view specs it is called like this

RSpec.describe 'something' do
  let!(:user) { FactoryGirl.create(:user) } # Note the "!" there
  before { include_current_user_helper { user } }

  # do stuff
end

Note: the call to let with bang is important as content inside the block will be executed lazily, outside of the test scope, and user will be nill if not


For me, worked with:

before { controller.stub!(:current_user).and_return(user) }

If you are doing unit testing of your controller you can simply stub your current_user in a before block, like this:

let(:user) { ... }

# RSpec version <= 2 syntax:
before { controller.stub(:current_user) { user } }

# RSpec version >= 3 syntax:
before { allow(controller).to receive(:current_user) { user } }

If you are doing feature or request testing, I advise you to perform a real log-in by creating a user in your database, then passing through your log-in page with this user credentials


Here you seem to be doing a feature test, you should write a helper that perform the creation of the user record and go through the log-in.

Additionally in feature testing to gain a lot of time while running your test, do not hesitate to group your assertions in the same block. Clearly, instead of:

it { should have_button('Submit')}
it { should have_link('Cancel')}
it { should have_content(user.fname+"\'s profile")}

You can write

it 'check links and content' do
  should have_button('Submit')
  should have_link('Cancel')
  should have_content(user.fname+"\'s profile")
end

That will avoid to generate several session of your feature environment, and also to log-in several times