I’m using RSpec (through the gem rspec-rails) for testing and developing
my application.
Then, I’ve tried to “test” a controller and run up against a something
that in last, I’m not understanding: post and get methods.
I’ve searched them in RoR doc, but their’s not documented.
In my route file:
controller :sessions do
post ‘login’, action: :login_create
get ‘login’, action: :login
get ‘logout’, action: :logout
end
At the beginning, I was thinking that post will simulate an http post
request at the specified url, while get a http get one, so I’ve writed:
describe “POST ‘login’” do
it “returns http success” do
post ‘login’
response.should be_success
response.should render_template ‘sessions/login_create’
end
end
But this will load the login action and not the login_create! After a
lot of searching and trying, I’ve wrote:
post :login_create
… And it works as expected. However, after that I’ve tried:
get :login_create
… And this works also! O_o
So, what this kind of methods really do and how are intended to be used?
Equals effect, but the one I’ve used is more succinct
In no programming language is succinct better than clarity. In my brief
exposure to Rails, it suffers a lot from ZERO clarity. I’d rather be
clear than succinct.
The problem isn’t in the route, but in the strange behavior of get and
post, instance methods of ActionController::TestCase::Behavior
My rspec tests seem to work as you would expect. I used a controller
named Dogs to test the routes:
require ‘spec_helper’
describe “Dogs Pages” do
describe “POST to /login” do
it “returns http success” do
post ‘/login’
response.should be_success
response.should render_template ‘dogs/login_create’
response.body.should include(‘hello world’)
end
end
describe “GET to /login” do
it “should have h1 of ‘Doggie’” do
visit ‘/login’
page.should have_selector(‘h1’, text: “Login”)
end
end
On Tuesday, September 4, 2012 12:56:05 AM UTC+1, Ruby-Forum.com User
wrote:
But this will load the login action and not the login_create! After a
lot of searching and trying, I’ve wrote:
post :login_create
… And it works as expected. However, after that I’ve tried:
get :login_create
… And this works also! O_o
Controller specs bypass your routes entirely (as part as action invocation
goes, they’re still used if you try to generate a url inside the
action).
If you do
get :action_name
then it will invoke that action with a get request, whether there’s a
route
for it or not.
post ‘/login’
fails because there are is no ‘/login’ action (but there is a ‘login’
one).
If you write an spec request spec (or a rails integration test) then
get/post are the rack test methods instead which do take actual paths.
Fred
So, what this kind of methods really do and how are intended to be used?
SessionsController POST to ‘login’ returns http success
Failure/Error: post ‘/login’
ActionController::RoutingError:
No route matches {:controller=>“sessions”, :action=>"/login"}
levels) in <top (required)>’
====================================================================
That’s rake routes:
login POST /login(.:format) sessions#login_create
GET /login(.:format) sessions#login
logout GET /logout(.:format) sessions#logout
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/registrati(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
describe SessionsController do
describe “GET ‘login’” do
before { get ‘login’ }
it "returns http success" do
response.should be_success
end
end
describe “POST ‘login’” do
it “returns http success” do
post ‘/login’
response.should be_success
response.should render_template ‘sessions/login_create’
end
end
describe “GET ‘logout’” do
it “returns http success” do
get ‘logout’
response.should be_success
end
end
end
If I change post '/login' with post 'login' it fails with:
F…
Failures:
SessionsController POST to ‘login’ returns http success
Failure/Error: response.should render_template
‘sessions/login_create’
expecting <“sessions/login_create”> but rendering with
<“sessions/login, layouts/application”>
By this error, it seems to me that post actually perform a get; really
strange @_@
7stud, which version of rails & rspec do you have? Mine:
rails (3.2.6)
railties (3.2.6)
rspec (2.11.0)
rspec-core (2.11.0)
rspec-expectations (2.11.1)
rspec-mocks (2.11.1)
rspec-rails (2.11.0)
One thing I’ve noted in your spec is that in the outermost describe you
pass a string. If I do that, rspec complains about uninitialized @controller; if I move the spec in spec/ dir (actually it’s in spec/controllers/), the post method isn’t found @@
What’s wrong with me? ..
On Tuesday, September 4, 2012 12:56:05 AM UTC+1, Ruby-Forum.com User
wrote:
Controller specs bypass your routes entirely (as part as action invocation
goes, they’re still used if you try to generate a url inside the
action).
If you do
get :action_name
then it will invoke that action with a get request, whether there’s a
route
for it or not.
post ‘/login’
fails because there are is no ‘/login’ action (but there is a ‘login’
one).
If you write an spec request spec (or a rails integration test) then
get/post are the rack test methods instead which do take actual paths.
Fred
If I’m getting what you say, in a controller spec it’s not really
important if I use get, post, delete or put methods - unless the action
itself has some logic affected by the request type, right?
On Wednesday, September 5, 2012 10:50:15 PM UTC+1, Ruby-Forum.com User
wrote:
If I’m getting what you say, in a controller spec it’s not really
important if I use get, post, delete or put methods - unless the action
itself has some logic affected by the request type, right?
Correct, although it would be more than a little perverse not to use the
request type you expect.