URL helpers not working in test

I've been neglecting these errors for a weeks because I don't know what's going on. My environment is rspec, capybara and factory_girl under Rails 3.1.3 and Ruby 1.9.2. I'm also using spork and guard but this happens without them.

The mailer tests are failing because apparently the UrlHelper isn't loaded.

1) User delivers email to user      Failure/Error: user.send_password_reset      ActionView::Template::Error:        No route matches {:action=>"edit", :controller=>"password_resets"}      # ./app/views/mailer/password_reset.text.erb:4:in `_app_views_mailer_password_reset_text_erb__1662523378608014744_70180362078380'      # ./app/mailers/mailer.rb:11:in `password_reset'      # ./app/models/user.rb:34:in `send_password_reset'      # ./spec/models/user_spec.rb:12:in `block (2 levels) in <top (required)>'

There is definitely a route for password_resets#edit (resources :password_resets) and it works in development and production, which is the confusing part. I think the tests aren't configured correctly in my spec_helper.rb -- the gist for that is here: spec_helper.rb · GitHub

While an outright answer would be nice, I'd like to get help on how to go about investigating this kind of thing better. Thanks in advance.

I think this one is a lesson in reading error messages closely. The error message is No route matches {:action=>"edit", :controller=>"password_resets"} and you protest that you've got resources :password_resets in your routes file. But to generate a url for a password reset edit, it needs to know which password reset you're editing (i.e. id is a mandatory parameter in that route). Since you've not passed an id parameter, rails can't match your parameters against the passwords reset edit action.

Fred

Thanks, Frederick. You're always here to answer questions and I appreciate that, as I'm sure are others. Your comment pointed me in the right direction. It was a race condition between clearing out the old token and creating the new one. So sometimes I'd get nil and other times a valid value. The mailer template was passing in an id: <%= edit_password_reset_url(@user.reset_token) %>

The user model had a function that reset the tokens, which it would call before generating a new one. It was using a slightly different method to set it than clear it and that caused a race condition. It needed to commit the changes to the database after clearing the token, and then generate a new one. It's an extra hit to the db but I don't expect this to be called too often.

Thanks again.