31

I wish to override the Devise::RegistrationsController to implement some custom functionalality. To do this, I've created a new RegistrationsController like so:

# /app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
  def new
    super
  end
end

and set up my routes like this:

devise_for :users, :controllers => { :registrations => "registrations" }

and tried to test it like this:

describe RegistrationsController do
  describe "GET 'new'" do
    it "should be successful" do
      get :new
      response.should be_success
    end
  end
end

but that gives me an error:

 1) RegistrationsController GET 'new' should be successful
 Failure/Error: get :new
 AbstractController::ActionNotFound:
   Could not find devise mapping for path "/users/sign_up".
   Maybe you forgot to wrap your route inside the scope block? For example:

       devise_scope :user do
         match "/some/route" => "some_devise_controller"
       end
 # ./spec/controllers/registrations_controller_spec.rb:13:in `block (3 levels) in <top (required)>'

So what am I doing wrong?

doub1ejack
  • 10,627
  • 20
  • 66
  • 125
David Tuite
  • 22,258
  • 25
  • 106
  • 176

2 Answers2

49

The problem is that Devise is unable to map routes from the test back to the original controller. That means that while your app actually works fine if you open it in the browser, your controller tests will still fail.

The solution is to add the devise mapping to the request before each test like so:

before :each do
  request.env['devise.mapping'] = Devise.mappings[:user]
end
user
  • 86,916
  • 18
  • 197
  • 190
David Tuite
  • 22,258
  • 25
  • 106
  • 176
  • What file do you add this to - I can't figure it out, thanks. – eWizardII Nov 12 '11 at 03:58
  • Put it in your controller tests, just inside the first `describe` block. – David Tuite Nov 12 '11 at 06:48
  • In spec - I have controllers the registration_controller is where I put it as follows to no avail: require 'spec_helper' describe RegistrationsController do describe "GET 'edit'" do before :each do request.env['devise.mapping'] = Devise.mappings[:user] end it "should be successful" do get 'edit' response.should be_success end end end – eWizardII Nov 12 '11 at 07:41
  • I'd suggest you make a new question. That's pretty hard to read! – David Tuite Nov 12 '11 at 07:43
  • Thanks, I updated my already open question on the matter here - http://stackoverflow.com/questions/8102511/infamous-abstractcontrolleractionnotfound-devise-rails – eWizardII Nov 12 '11 at 07:49
  • See this wiki page: https://github.com/plataformatec/devise/wiki/How-To:-Controllers-and-Views-tests-with-Rails-3-%28and-rspec%29 – Jared Beck Apr 20 '12 at 05:27
  • You're brilliant. How on earth did you figure this out? – Stephen Corwin Nov 29 '12 at 02:07
  • took me forever to find this answer. Thanks. For those using newer version and might encounter `Devise::MissingWarden` error refer to [this SO thread](https://stackoverflow.com/questions/38421853/why-is-my-rspec-not-loading-devisetestcontrollerhelpers) – Community Feb 21 '19 at 03:33
-2

Your route should look like this:

devise_for :users, :controllers => { :registrations => "registrations" } do
  get "/users/sign_up/:invitation_token" => 'registrations#new'
end
David Tuite
  • 22,258
  • 25
  • 106
  • 176
Kevin Tsoi
  • 1,807
  • 15
  • 16
  • That's what I have? The only difference is the hash synatax -> `registrations:` vs `:registrations =>`. That shouldn't make a difference unless I run my app in Ruby < 1.9.2. – David Tuite Jul 12 '11 at 07:09
  • Ah, ok. Didnt know that. Never seen that syntax before. Thanks. – Kevin Tsoi Jul 12 '11 at 07:31
  • ;) It's much nicer when you get used to it! I think it'll edit my question anyway, just in case It confuses anyone. – David Tuite Jul 12 '11 at 07:37