Rails 5.2.0+Devise 4.4.3测试报错undefined method `users_url'求助
Alright, let's break down why you're hitting that undefined method 'users_url' error in your test environment while development and production work fine—this is almost always tied to your locale route scope interacting with Devise's routing helpers. Here are the most likely causes and fixes:
1. Your test cases aren't passing the locale parameter
Since you've wrapped your routes in a locale scope (like scope '(:locale)' do ... end), Devise generates routing helpers that require a locale argument (e.g., users_url(locale: :en) instead of just users_url). If your test suite isn't providing this parameter when making requests, Rails can't find the matching helper method.
Fix:
Update your test cases to include the locale parameter when calling route helpers. For example:
# In your UsersTest test "creating a user" do post users_url(locale: I18n.default_locale), params: { user: { email: "test@example.com", password: "password123" }, # Add your reCAPTCHA params here if needed } # Assertions follow... end
Alternatively, you can set a default locale in your test setup to avoid repeating it:
# In test/test_helper.rb setup do I18n.locale = :en # or your default locale end
2. Your custom RegistrationsController isn't handling locale in routing
When you use respond_with in your custom controller (especially in the check_captcha method or create action), Devise might be trying to redirect using the un-scoped users_url helper, which doesn't exist because of your locale scope.
Fix:
Either explicitly pass the locale to your redirect location, or set default URL options for the controller to automatically include the locale:
Option A: Explicitly set location in respond_with
# In registrations_controller.rb def create super do |resource| if resource.persisted? respond_with resource, location: users_url(locale: I18n.locale) else # Handle validation errors end end end
Option B: Set default URL options for the controller
Add this method to your RegistrationsController to ensure all routing helpers from this controller include the current locale:
# In registrations_controller.rb def url_options { locale: I18n.locale }.merge(super) end
3. Devise routes aren't wrapped in the locale scope
If your devise_for :users route is defined outside your locale scope block, the generated routing helpers won't account for the locale parameter, creating a mismatch between your controller's expectations and the actual route helpers available.
Fix:
Double-check your config/routes.rb to ensure Devise is inside the locale scope:
# Correct setup scope '(:locale)', locale: /en|zh/ do # Adjust locales to match your app devise_for :users, controllers: { registrations: 'registrations' } # Other routes... end
4. Test environment route cache is stale
Sometimes Rails caches routes in the test environment, and changes to your route configuration might not be reflected until you clear the cache.
Fix:
Run this command to clear test environment cache:
rails tmp:clear RAILS_ENV=test
Then re-run your test suite.
内容的提问来源于stack exchange,提问作者127

