I would be grateful if somebody could let me know how to test actions on a controller which are intercepted by a before_filter requiring a login. The catch is that the before_filter is on my application controller and I am trying to test my users controller.
I have functional tests for the login and logout actions on their own controller. Now I just want to be able to post a valid username and password into that controller, from my users controller, so I can just get on with testing my users controller's actions.
In a functional test you can simply populate the session… the functional test really should only test the method itself, not the login. It’s common practice to put the user’s id in the session… so in a functional test we can just populate the session… In this example, I am assuming that session[:user_id] will be 1 (the id of my logged in user).
def test_edit_user
passing the session should get me there
get :edit, {:id=>1}, {:user_id => 1}
assert_response :success
end
def test_edit_user_without_login
no session? should get denied
get :edit, {:id=>1}
assert_response :redirect
assert flash[:notice] = “Please log in.”
end
Testhing the integration of logins with other actions can be done using Integration tests
def test_edit_user
get “/user/edit/1” #gets the edit page
assert_response :redirect # should be redirected to the login page
follow_redirect #follow that redirect
post “/main/login” , {:username=>“homer”, :password=>“simpson”} # post username and password
assert_response :redirect # login should redirect you back to the url they wanted to go to originally
follow_redirect # follow that redirect
assert_response :success # Was it successful?
assert_template “edit” # was it the edit page??
end
My feeling is that functional tests are meant to act as unit tests for a controller. You don’t want any dependencies, you just want to test their behavior. Integration tests should test the dependencies.
the functional test really should only test the method itself, not the login.
Good -- that's what I would like to do.
It's common practice to put the user's id in the session... so in a functional test we can just populate the session... In this example, I am assuming that session[:user_id] will be 1 (the id of my logged in user).
That works well for me. Stuffing the user_id into the session successfully passes my login filter.
def test_edit_user
# passing the session should get me there
get :edit, {:id=>1}, {:user_id => 1}
assert_response :success
end
Aha! I didn't know that passing a second hash set up the session; that's good to learn. (I can't find it in the API docs though?)
Testhing the integration of logins with other actions can be done using Integration tests
Oh, okay. So a functional test can only test one controller and integration tests are for spanning multiple controllers.
My feeling is that functional tests are meant to act as unit tests for a controller. You don't want any dependencies, you just want to test their behavior. Integration tests should test the dependencies.
That confirms what I thought. I just wasn't quite sure how to bypass the dependencies for the functional tests.
Does that help?
Yes it does, Brian, thank you. You've taught me a new way to pass session parameters and confirmed the way to proceed.
1. Have login test helper with login_as and logout methods. Those methods set appropriate @ request.session values.
2. When I just need to run functional tests assuming that user is logged in, I do login_as :some_user in my test's setup method:
[snip]
3. You can also add some sugar:
[snip]
That's all good stuff -- thank you. I'll make use of it.