Jeffrey W.
Jeffrey W.

Reputation: 4169

All Ruby tests raising: undefined method `authenticate' for nil:NilClass

Most of my tests are raising the following and I don't understand why. All methods call raise the 'authenticate' error. I've checked the code if there was a method called "authenticate" but there is no such method.

  1) Admin::CommentsController handling GET to index is successful
     Failure/Error: get :index
     undefined method `authenticate!' for nil:NilClass
     # ./spec/controllers/admin/comments_controller_spec.rb:9:in `block (3 levels) in <top (required)>'


  124) PostsController handling GET for a single post should render show template
     Failure/Error: get :show, :year => '2008', :month => '01', :day => '01', :slug => 'a-post'
     undefined method `authenticate' for nil:NilClass
     # ./app/controllers/application_controller.rb:18:in `set_current_user_for_model'
     # ./spec/controllers/posts_controller_spec.rb:131:in `do_get'
     # ./spec/controllers/posts_controller_spec.rb:140:in `block (3 levels) in <top (required)>'

The project can be found over there => https://github.com/agilepandas/enki in case you'd like to run the tests your self.

Upvotes: 132

Views: 39778

Answers (8)

Cathal Curtis
Cathal Curtis

Reputation: 21

I was experiencing the same failures in one of my projects. It is using Ruby 2.0.0-p598, Rails 3.2.21, RSpec 2.99. When I run all specs together the problem occurred. When I ran the specs individually, they passed. I have the following included in my spec/spec_helper.rb:

RSpec.configure do |config|
  # ...
  config.include Devise::TestHelpers, type: :controller
  # ...
end

I added the following to the first describe in each failing spec file. This did not resolve the problem:

before :each do
  sign_out :user
end

Neither did:

after :each do
  sign_out :user
end

Taking inspiration from the answer to this stackoverflow question, I ran different combinations of rspec directories together to find out which ones could be interfering with each other. In the end I discovered I was calling:

before() do #note no :each passed to before
  :
end

when I changed all occurrences of this to:

before(:each) do
  :
end

All the specs passed without the failure:

undefined method `authenticate' for nil:NilClass

I hope this is of help to others.

Upvotes: 2

Pete
Pete

Reputation: 10680

If you're working with view spec, you can stub of current_user. This effectively overrides the current_user helper called from your view with whatever is returned. Here's how with rspec-3.2.3:

RSpec.describe "projects/show", type: :view do
  before(:each) do
    allow(view).to receive(:current_user).and_return(FactoryGirl.create(:user))
  end

  it "renders attributes in <p>" do
    render
    expect(rendered).to match(/whatever you want to regex match here/)
  end
end

Upvotes: 0

equivalent8
equivalent8

Reputation: 14237

in RSpec

as Jeffrey W. mentioned, in his answer above -> to set this to all controllers:

RSpec.configure do |config|
  # ...
  config.include Devise::TestHelpers, type: :controller
  # ...
end

however, if this is relevant to just one spec, you don't necessarily need to include devise helpers to all your controllers specs, you can just explicitly include those helpers in that one controller describe block:

require 'spec_helper'
describe MyCoolController
  include Devise::TestHelpers

  it { } 
end

Upvotes: 9

Jonathan Lin
Jonathan Lin

Reputation: 20754

The above answer did not work for me (RSpec 3.1)

See https://stackoverflow.com/a/21166482/1161743 for a solution that worked for me.

You will need to log out an anonymous user before setting up variables:

before :each do
  sign_out :user
end

Upvotes: 8

Jeffrey W.
Jeffrey W.

Reputation: 4169

This question has been answered on Twitter by @MatthewClosson

@jeffehh You need to create a spec/support/devise.rb file as specified here https://github.com/plataformatec/devise#test-helpers to include the devise test helpers #ruby

Thanks once again.

Upvotes: 191

Boris Stitnicky
Boris Stitnicky

Reputation: 12588

Ruby is telling you, that method #authenticate has not been definded on nil yet. You can do it easily by:

def nil.authenticate!
  puts "Bingo! Nil is now authentic!"
end

And the error will go away.

Upvotes: -20

Tim Fletcher
Tim Fletcher

Reputation: 7396

I'm aware you're using Rspec but you can run into this same issue with Test::Unit. You just need to add the devise test helpers to test/test_helper.rb

class ActiveSupport::TestCase
  include Devise::TestHelpers
end

Upvotes: 74

Berin Loritsch
Berin Loritsch

Reputation: 11473

It looks like there are some updates to the source code. The ApplicationController specifies that there needs to be an authenticate_user! filter run before any request. This thread provides some background on issues with it:

http://groups.google.com/group/plataformatec-devise/browse_thread/thread/f7260ebe2d9f7316?fwc=1

Essentially, the authenticate_user! function is part of Rails 3 (using the new devise feature, of which I know little about). If the app can't find the User model (either because of namespace issues or whatever reason) then the method will fail. The "enki" application you linked to is now a Rails 3 application. It could be experiencing a few growing pains as it converts over.

Upvotes: -3

Related Questions