Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test helpers don't work on the Rails main branch (8.0.0.alpha) #5694

Open
jeromedalbert opened this issue Jun 14, 2024 · 0 comments · May be fixed by #5695
Open

Test helpers don't work on the Rails main branch (8.0.0.alpha) #5694

jeromedalbert opened this issue Jun 14, 2024 · 0 comments · May be fixed by #5695

Comments

@jeromedalbert
Copy link

jeromedalbert commented Jun 14, 2024

Environment

  • Ruby 3.3.2
  • Rails main (8.0.0.alpha)
  • Devise 4.9.4

Current behavior

When using the sign_in Devise test helper method in a controller or integration test, I get the following error:

Error:
HelloControllerTest#test_index:
RuntimeError: Could not find a valid mapping for #<User id: nil, email: nil, created_at: nil, updated_at: nil>
    c/tmp/devise/lib/devise/mapping.rb:46:in `find_scope!'
    c/tmp/devise/lib/devise/test/integration_helpers.rb:38:in `sign_in'
    repro.rb:59:in `test_index'

Here is a minimal reproduction of the issue (run this with ruby repro.rb):

# repro.rb
require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'rails', github: 'rails/rails', branch: 'main'
  gem 'devise', '~> 4.9.4'
  gem 'sqlite3', '~> 1.4'
end

require 'rails'
require 'action_controller/railtie'
require 'active_record'
require 'minitest/autorun'
ENV['RAILS_ENV'] = 'test'

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Schema.define do
  create_table :users do |t|
    t.string :email, null: false
    t.string :encrypted_password, null: true
    t.timestamps null: false
  end
end

Devise.setup do |config|
  require 'devise/orm/active_record'
end

class MyApp < Rails::Application
  config.eager_load = false

  routes.append do
    root to: 'hello#index'
    devise_for :users
  end
end

class User < ActiveRecord::Base
  devise :database_authenticatable
end

MyApp.initialize!

class ApplicationController < ActionController::Base
end

class HelloController < ApplicationController
  before_action :authenticate_user!

  def index
    render plain: 'Hello'
  end
end

class HelloControllerTest < ActionDispatch::IntegrationTest
  include Devise::Test::IntegrationHelpers

  def test_index
    sign_in User.new

    get '/'

    assert_response :success
  end
end

Expected behavior

Tests should pass:

.

Finished in 0.023595s, 42.3819 runs/s, 42.3819 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips

Additional information

Last week deferred route drawing was merged into Rails master to improve boot times for larger apps with lots of routes. Routes are now lazy loaded for Rails environments that have config.eager_load disabled, which is the case by default for the development and test environments.

Basically by default for the test environment, whenever a route is visited, routes get lazy loaded. Devise's mappings aren't loaded when the test starts, they are only loaded when the test visits a route, because Devise's entry point is defined in the route files with devise_for or devise_scope.

But in integration and controller tests you typically call the sign_in helper before visiting the route. At this point Devise mappings and scopes aren't loaded yet, so Devise will error out.

cc @gmcgibbon

Potential fix: #5695

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

1 participant