Controllers specs don't currently work on the Rails main branch (8.0.0.alpha)
Closed this issue · 5 comments
What Ruby, Rails and RSpec versions are you using?
Ruby version: 3.3.1
Rails version: main branch (8.0.0.alpha)
RSpec version: 6.1.2
Observed behaviour
When running a controller spec, I get the following error (see reproduction steps in the reproduction section of this issue):
Failures:
1) HelloController#index
Failure/Error: before { get :index }
ActionController::UrlGenerationError:
No route matches {:action=>"index", :controller=>"hello"}
Expected behaviour
Spec should pass:
.
Finished in 0.0127 seconds (files took 0.39717 seconds to load)
1 example, 0 failures
Can you provide an example reproduction?
Here is a minimal reproduction of the issue:
# my_app.rb
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'rails', github: 'rails/rails', branch: 'main'
gem 'rspec-rails', '6.1.2'
end
require 'rails'
require 'action_controller/railtie'
require 'rspec/rails'
class MyApp < Rails::Application
config.eager_load = false
routes.append { root to: 'hello#index' }
end
MyApp.initialize!
class HelloController < ActionController::Base
def index
render plain: 'Hello'
end
end
describe HelloController, type: :controller do
describe '#index' do
before { get :index }
it { expect(response).to be_successful }
end
end
RSpec::Core::Runner.run([$__FILE__])Run this file with ruby my_app.rb, and the spec should fail. It passes if you change to gem 'rails', github: 'rails/rails', ref: 'a27a1751cfd499f69499e943f12e3400b55a323e', and fails for the commit with gem 'rails', github: 'rails/rails', ref: 'e97db3b3957781c781a61fb01265feb2b57688bb'. Here is a link to the commit: rails/rails@e97db3b.
Additional information
- Since that commit is very recent (last week) I wasn't sure whether to file a bug here or in https://github.com/rails/rails. I decided to file it here.
- A current workaround to make the spec pass is to add
before { Rails.application.reload_routes! }in the spec, orconfig.before(:suite) { Rails.application.reload_routes! }in your rails helper.
@jeromedalbert I see your example failing. I'm not sure if you noticed but changing to eager_load makes your example pass:
class MyApp < Rails::Application
config.eager_load = true
routes.append { root to: 'hello#index' }
endNote, rails defaults to eager load in test for CI in new apps.
Yeah, the main issue is when running tests on one's local, since it's not a CI environment and eager load is disabled by default.
A current workaround to make the spec pass is to add before { Rails.application.reload_routes! } in the spec, or config.before(:suite) { Rails.application.reload_routes! } in your rails helper.
I wonder if makes sense to eager load routes before it tries to fetch the routes in the specific types of example groups: controller, request, routing, system by adding something like:
routes_reloader = ::Rails.application.routes_reloader
routes_reloader.execute_unless_loaded if routes_reloader&.respond_to?(:execute_unless_loaded)Looks like the commit that introduced deferred routes was reverted, and Rails main is working at the moment.
Thanks for the heads-up. Can this be closed, or is there anythibg actionable left?