Testing named routes or url_for in functional test
If you’ve ever tried using named routes or url_for in functional tests, you might have seen an error like this:
1) Error:
test_article_override_to_meta(ArticleControllerTest):
NoMethodError: You have a nil object when you didn't expect it!
The error occured while evaluating nil.rewrite
/usr/local/lib/ruby/gems/1.8/gems/actionpack-1.12.1/lib/action_controller/base.rb:461:in `url_for'
generated/routing/named_routes/article.rb:2:in `article_url'
/usr/local/lib/ruby/gems/1.8/gems/actionpack-1.12.1/lib/action_controller/test_process.rb:431:in `method_missing'
test/functional/article_controller_test.rb:32:in `test_article_override_to_meta'
What is happenening here is that ActionController uses the current request as its context for creating new urls, so for instance if you do url_for :action => "create"
it will use the current controller from the current request. So, if you write a functional test that tries kick things off with url_for (or a named route, which really just calls url_for under the covers) it fails as there is no current url.
Tracing into ActionController, @url gets created by a private method which is in the whole request cycle - so mocking it out probably isn’t worth the trouble.
The solution is simple - call a simple, easy url (preferably without side effects - like index) before you use the named route or url_for. For example:
[ruby] def test_article_url get :index url = article_url :controller => “article”, :id => 1234 assert_equal “https://host/article/1234”, url end [/ruby]
If you wanted to keep this drier you could move the get :index into your setup or into a helper method if it only applies to some of your test cases.