heartcombo / devise

Flexible authentication solution for Rails with Warden.
http://blog.plataformatec.com.br/tag/devise/
MIT License
24.01k stars 5.55k forks source link

Rails 8: test helpers do not work #5705

Open jeromedalbert opened 3 months ago

jeromedalbert commented 3 months ago

Environment

Steps to reproduce

Run the following bash commands (tested on macOS):

rails new myapp --main
cd myapp
bundle add devise
rails generate devise:install
rails generate devise User
rm test/fixtures/users.yml
rails db:migrate

sed -i '' 's/end$/  root "hello#index"\nend/' config/routes.rb

echo 'class HelloController < ApplicationController
  def index
    authenticate_user!
    render plain: "Hello"
  end
end' > app/controllers/hello_controller.rb

echo 'require "test_helper"
class HelloControllerTest < ActionDispatch::IntegrationTest
  include Devise::Test::IntegrationHelpers
  def test_index
    sign_in User.new
    get "/"
    assert_response :success
  end
end' > test/integration/hello_controller_test.rb

BACKTRACE=1 rails test test/integration/hello_controller_test.rb

Current behavior

I get the following error:

Error:
HelloControllerTest#test_index:
RuntimeError: Could not find a valid mapping for #<User id: nil, email: [FILTERED], created_at: nil, updated_at: nil>
    devise (4.9.4) lib/devise/mapping.rb:46:in `find_scope!'
    devise (4.9.4) lib/devise/test/integration_helpers.rb:38:in `sign_in'
    test/integration/hello_controller_test.rb:5:in `test_index'
    minitest (5.24.1) lib/minitest/test.rb:95:in `block (3 levels) in run'
    minitest (5.24.1) lib/minitest/test.rb:192:in `capture_exceptions'
    minitest (5.24.1) lib/minitest/test.rb:90:in `block (2 levels) in run'
    minitest (5.24.1) lib/minitest.rb:368:in `time_it'
    minitest (5.24.1) lib/minitest/test.rb:89:in `block in run'
    minitest (5.24.1) lib/minitest.rb:467:in `on_signal'
    minitest (5.24.1) lib/minitest/test.rb:240:in `with_info_handler'
    minitest (5.24.1) lib/minitest/test.rb:88:in `run'
    rails (e13b251ae078) activesupport/lib/active_support/executor/test_helper.rb:5:in `block in run'
    rails (e13b251ae078) activesupport/lib/active_support/execution_wrapper.rb:104:in `perform'
    rails (e13b251ae078) activesupport/lib/active_support/executor/test_helper.rb:5:in `run'
    minitest (5.24.1) lib/minitest.rb:1200:in `run_one_method'
    minitest (5.24.1) lib/minitest.rb:433:in `run_one_method'
    minitest (5.24.1) lib/minitest.rb:420:in `block (2 levels) in run'
    minitest (5.24.1) lib/minitest.rb:419:in `each'
    minitest (5.24.1) lib/minitest.rb:419:in `block in run'
    minitest (5.24.1) lib/minitest.rb:467:in `on_signal'
    minitest (5.24.1) lib/minitest.rb:454:in `with_info_handler'
    minitest (5.24.1) lib/minitest.rb:418:in `run'
    rails (e13b251ae078) railties/lib/rails/test_unit/line_filtering.rb:10:in `run'
    minitest (5.24.1) lib/minitest.rb:332:in `block in __run'
    minitest (5.24.1) lib/minitest.rb:332:in `map'
    minitest (5.24.1) lib/minitest.rb:332:in `__run'
    minitest (5.24.1) lib/minitest.rb:288:in `run'
    minitest (5.24.1) lib/minitest.rb:86:in `block in autorun'

Expected behavior

Test should pass:

.

Finished in 0.106683s, 9.3736 runs/s, 9.3736 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips

Workaround

A workaround is to use one of those before the sign_in call:

Additional information

bugloper commented 2 months ago

Mine worked after adding devise_for :users in the route file. Note: Mine was graphql application so, I did not have this added initially.

iRonin commented 3 weeks ago

Temp workaround:

RSpec.configure do |config|
  …
  # TODO Remove when Devise fixes https://github.com/heartcombo/devise/issues/5705
  config.before(:each, type: :controller) do
    Rails.application.reload_routes_unless_loaded
  end
end
mattbrictson commented 3 weeks ago

In my case, the tests that were failing were the ones indirectly involving Devise::Mailer. This mailer actually gets invoked pretty often, because creating a user in a test (e.g. via FactoryBot) will try to send a confirmation email by default as a side-effect.

Anyway, here is the workaround I added to my test_helper.rb:

ActiveSupport.on_load(:action_mailer) do
  Rails.application.reload_routes_unless_loaded
end
epugh commented 1 week ago

This also worked for me in my test_helper.rb. Thanks for sharing, I never would have grokked this fix!

le0pard commented 4 days ago

Looks like it is influence not only on tests, but also registration is not working in application due to same error