get & post methods in controller's test

30 views
Skip to first unread message

Salvatore Pelligra

unread,
Sep 3, 2012, 7:55:25 PM9/3/12
to rubyonra...@googlegroups.com
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?

--
Posted via http://www.ruby-forum.com/.

7stud --

unread,
Sep 4, 2012, 1:01:11 AM9/4/12
to rubyonra...@googlegroups.com
How about:


controller :sessions do
match '/login' => :login_create, :via => :post
match '/login' => :login, :via => :get
match '/logout' => :logout
end

Salvatore Pelligra

unread,
Sep 4, 2012, 12:42:01 PM9/4/12
to rubyonra...@googlegroups.com
7stud -- wrote in post #1074532:
> Your route syntax is confusing to me. How about:
>
>
> controller :sessions do
> match '/login' => :login_create, :via => :post
> match '/login' => :login, :via => :get
> match '/logout' => :logout
> end
>
> ...which is pieced together from here:
>
> http://api.rubyonrails.org/classes/ActionDispatch/Routing.html

Equals effect, but the one I've used is more succinct :)
It also explained in "HTTP helper methods" paragraph of the linked api.

The problem isn't in the route, but in the strange behavior of get and
post, instance methods of ActionController::TestCase::Behavior

7stud --

unread,
Sep 4, 2012, 6:27:14 PM9/4/12
to rubyonra...@googlegroups.com
> 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


end


If I change the 'post' to 'get', that test fails.

Salvatore Pelligra

unread,
Sep 5, 2012, 3:47:00 PM9/5/12
to rubyonra...@googlegroups.com
That's strange °_° In my app it fails:
====================================================================
.F.

Failures:

1) SessionsController POST to 'login' returns http success
Failure/Error: post '/login'
ActionController::RoutingError:
No route matches {:controller=>"sessions", :action=>"/login"}
# ./spec/controllers/sessions_controller_spec.rb:15:in `block (3
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
====================================================================


And this is the failing spec:
====================================================================
require 'spec_helper'

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:

1) 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">
# ./spec/controllers/sessions_controller_spec.rb:17:in `block (3
levels) in <top (required)>'
====================================================================

By this error, it seems to me that post actually perform a get, really
strange @_@

7stud, which versions 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? ._.

Frederick Cheung

unread,
Sep 5, 2012, 5:38:17 PM9/5/12
to rubyonra...@googlegroups.com

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

Salvatore Pelligra

unread,
Sep 5, 2012, 5:49:33 PM9/5/12
to rubyonra...@googlegroups.com
Frederick Cheung wrote in post #1074851:
> 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? :)

7stud --

unread,
Sep 6, 2012, 12:39:05 AM9/6/12
to rubyonra...@googlegroups.com
Sorry, my tests were inside an integration('request') test:

/spec/requests/dog_pages_spec.rb

In my rails tutorial book, it says that inside a controller test, you
can't use urls at all, e.g

get '/about'
get '/'

...you can only do:

get 'actionA'
get 'actionB'

Frederick Cheung

unread,
Sep 6, 2012, 5:34:15 AM9/6/12
to rubyonra...@googlegroups.com
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.

Fred 

Salvatore Pelligra

unread,
Sep 6, 2012, 9:35:31 AM9/6/12
to rubyonra...@googlegroups.com
Ok, thanks to both of you for clearing my mind :)
Reply all
Reply to author
Forward
0 new messages