132
votes

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.

8

8 Answers

191
votes

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.

74
votes

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
9
votes

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
8
votes

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
2
votes

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.

0
votes

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
-3
votes

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.

-20
votes

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.