Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSpec tests with devise: could not find valid mapping

I'm trying to run controller specs with devise 1.3.4. (and factory girl) I followed the instructions in the git wiki for the project. I am able to log in as a user using the login_user method created in the macro, but login_admin fails with the following error:

...
sign_in Factory.create(:admin)

Could not find a valid mapping for #<User id: 2023, email: "[email protected]", .... >

Factory:

Factory.define :user do |f|
  f.sequence(:username) {|n| "user#{n}"}
  f.sequence(:email) {|n| "user#{n}@gmail.com"}
  f.email_confirmation {|fac| fac.email }
  f.password "a12345Den123"
  f.password_confirmation "a12345Den123"
#  f.admin 0
end

Factory.define :admin, :class => User do |f|
  f.sequence(:username) {|n| "admin#{n}"}
  f.sequence(:email) {|n| "admin#{n}@gmail.com"}
  f.email_confirmation {|fac| fac.email }
  f.password "a12345Den123"
  f.password_confirmation "a12345Den123"
  f.admin 1
end

Controller macros module:

module ControllerMacros
  def login_admin
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user]  #it should map to user because admin is not a model of its own.  It produces the same result either way.
      @admin = Factory.create(:admin)
      sign_in @admin
    end
  end

  def login_user
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user]
      @user = Factory.create(:user)
      sign_in @user
    end
  end
end

routes

devise_for :users
devise_for :admins, :class_name => 'User'

One solution is to set cache_classes = false, however that isn't ideal as I use spork and don't want to have to restart it after changing a model.

Any help?

like image 261
recursive_acronym Avatar asked Feb 25 '23 05:02

recursive_acronym


1 Answers

I have something like this in my routes:

  devise_for :accounts, :controllers => {:confirmations => "confirmations"} do
    put "confirm_account", :to => "confirmations#confirm_account"
    get "login" => "devise/sessions#new", :as => :login
    delete "logout" => "devise/sessions#destroy", :as => :logout
    get "register" => "devise/registrations#new", :as => :register
  end

so in my spec/support/controller_macros.rb I needed to change from:

  def login_account
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:account]
      @account = Factory.create(:account)
      sign_in(@account)
    end
  end

to

  def login_account
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:account]
      @account = Factory.create(:account)
      sign_in(:account, @account)
    end
  end

note the sign_in(scope, resource)

I hope this helps.

like image 138
Cezar Halmagean Avatar answered Mar 06 '23 19:03

Cezar Halmagean