This project is archived and is in readonly mode.
Functional tests don't care about http-verb that you use on the simulate request.
Reported by Fernando Guillen | November 15th, 2010 @ 03:09 PM
Context:
Rails: 3.0.1
Ruby: 1.8.7
In case I have these routes:
resources :my_things do
collection do
get :my_get_action
post :my_post_action
end
end
I can simulate this request in my functional test without any warning:
# my_things_controller_test.rb
post(:my_get_action)
get(:my_post_action)
What it looks like is that it doesn't matter which request type do you use.
See this very simple Rails project that reproduce this behavior in its functional tests:
These are the tests I'm trying:
require 'test_helper'
class MyThingsControllerTest < ActionController::TestCase
test "should respond to the get action" do
get(:my_get_action)
assert_response :success
assert_equal("my get action", @response.body)
end
test "should respond to the post action" do
post(:my_post_action)
assert_response :success
assert_equal("my post action", @response.body)
end
test "should respond to the get action with post verb" do
assert_raise(ActionController::RoutingError) do
post(:my_get_action)
end
end
test "should not respond to the post action with get verb" do
assert_raise(ActionController::RoutingError) do
get(:my_post_action)
end
end
end
This is the result:
$ rake test:functionals
(in /Users/fguillen/Develop/Rails/Contribute/TestingRoutesVerb)
Loaded suite /Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader
Started
F.F.
Finished in 0.180686 seconds.
1) Failure:
test_should_not_respond_to_the_post_action_with_get_verb(MyThingsControllerTest) [/test/functional/my_things_controller_test.rb:25]:
<ActionController::RoutingError> exception expected but none was thrown.
2) Failure:
test_should_respond_to_the_get_action_with_post_verb(MyThingsControllerTest) [/test/functional/my_things_controller_test.rb:19]:
<ActionController::RoutingError> exception expected but none was thrown.
4 tests, 6 assertions, 2 failures, 0 errors
rake aborted!
Command failed with status (1): [/System/Library/Frameworks/Ruby.framework/...]
Comments and changes to this ticket
-
Andrew White November 17th, 2010 @ 05:49 PM
- State changed from new to invalid
- Importance changed from to Low
Functional tests call the controller action directly and don't go through the router. Use an ActionDispatch::IntegrationTest to check the routing constraints. e.g:
rails generate test_unit:integration my_controller_routing
-
Fernando Guillen November 17th, 2010 @ 08:09 PM
But then what is the propose of having the five verbs in the
ActionController::TestCase
if I can use any of them without any restriction or diference?It is not intuitive.
And besides the
ActionController::TestCase
, some way, looks to the defined routes because if don't have the route defined on yourroutes.rb
it raises anActionController::RoutingError
. -
Andrew White November 18th, 2010 @ 07:05 AM
The get, post, etc. methods are just wrappers around the process method of ActionController::TestCase. All they do is set the REQUEST_METHOD header in the Rack environment so that any code in your controller that is dependent on the request method acts appropriately, e.g.
# routes.rb match '/basket', :to => 'shop#basket', :via => [:get, :post] # app/controllers/shop_controller.rb class ShopController < ApplicationController before_filter :load_basket def basket @basket.update(params[:basket]) if request.post? end protected def load_basket @basket = Basket.new(session[:basket]) end end
The routing error you get is because the process method builds a request uri so it's a generation error and not a recognition error (generation of urls ignores HTTP verbs as well).
Functional tests are meant to be isolated tests of your controller - if you need to test the full stack use an integration test.
-
Fernando Guillen November 18th, 2010 @ 09:58 AM
Ok, I understand pretty much better all this behavior.
So the verbs in the
ActionController::TestCase
are just to mark this request with this REQUEST_METHOD header in order to be used (or not) in ourController
.And also I have realized that we are also checking that the url we are calling can be built based on our routes definition, but without taken care about the verbs restrictions. So it should be able to be generated but it doesn't need to be recognized.
(This last point sounds a few inconsistent for me, but I understand I don't have the whole picture in my mind)
Thanks for your explanation.
-
Andrew White November 18th, 2010 @ 10:29 AM
That's pretty much it except the route is being built so that the REQUEST_URI header can be set and not to check whether the route can be generated (though it obviously it needs to be).
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>