I’ve spent a fair chunk of time this morning trying to get my functional tests on my rails app working with the login component. Here’s the result of my time, presented in the hopes that it will help someone else who’s stuck on the same thing.
I’m using ModelSecurity for the user login component because I’d also like to use the model security bits. Since I’ve got a before_filter to verify a user is logged in in my controller, I need to log in the user before I can test anything. Logging in the user is easy, right - I just post to the login action of the user controller. Here it is, wrapped in a function because I’ll have to call it multiple times:
def login_Neo
post :login, :user=>{:login=>users(:neo).login, :password=>NEO_PASSWORD}
end
def test_list
login_Neo
get :list
assert_response :success
assert_template 'list'
assert_not_nil assigns(:recipes)
end
Ok, I’m sure that I’ve got a problem because my controller doesn’t have a login action, but I decided to run it and see what happens.
Expected response to be a <:success>, but was <302>
Yep, I’m being redirected to the user controller because of my before_filter.
Now, I know that I need to make it post to the user controller, not the recipedex controller. Much googling, reading and thinking later, I discover that the post method being used here is defined in ActionPack from Rails. And, once I dig up the source for that, I discovered that post simply uses the @controller instance variable.
Aha! One simple change and I’m on my way:
def login_Neo
controller_bak = @controller
@controller = UserController.new
post :login, :user=>{:login=>users(:neo).login, :password=>NEO_PASSWORD}
@controller = controller_bak
end
Now, it posts where I want it to, sets User.current as I expect and everything works!
Entries (RSS)
February 16th, 2006 at 11:43 am
I was stuck on just this thing. Thanks for posting the solution!
Michael
February 16th, 2006 at 8:42 pm
I’m glad I was able to help.
-Matt
June 13th, 2006 at 7:06 am
Thanks for a simple solution to my insolvable problem. I have one question though. Where do you put your function login_Neo? Is it possible to have accessible from all test-files?
Anders
June 13th, 2006 at 9:34 am
Hi Anders - You can put the login_Neo function in your test_helper.rb file. That way it’ll be available in all of your test scripts. For what it’s worth, I’ve moved away from ModelSecurity and am now using acts_as_authenticated. I had too many problems getting the testing to work correctly and it didn’t seem like ModelSecurity was being developed at all. If I need it, I can go back to ModelSecurity for actually securing my models, but I found the user authentication/authorization more usable in acts_as_authenticated.
-Matt
July 11th, 2006 at 2:49 pm
Anders thanks for solving the post problem, a little compensation for ya, here’s the helper I created with it:
# Swap the controller for the length of the block, then switch back
def swap_controllers(new_controller, &block)
old_c = @controller
@controller = new_controller
yield
@controller = old_c
end
Allows for:
# From within ConvsController
# Destroy a conv from PagesController then verify returns to Convs …
swap_controllers(PagesController.new) {
get :service
swap_controllers(ConvsController.new) {
check_try_destroy(20) {|id| is_destroyed(id)}
assert_redirected_to :controller => “pages”, :action => “service”
}
}
July 11th, 2006 at 9:40 pm
Thanks for that, Brittain. Looks like a nice little bundling of the functionality.
I haven’t worked with it yet, but Integration Testing (available with Rails 1.1) should take care of this issue for us in a nice clean way.
-Matt
July 12th, 2006 at 10:53 am
Awesome Matt. This is just what I was looking for.
Thanks