The first thing to do is to shift as much as you can out of the controllers. If at all possible, put in in a model or a library, and then just unit test them. However, that is not always easy, say because you want to invoke a redirect from the method or you need quick access to the session (I expect you could handle the session in a library file, but I think it would be messy and more trouble than it is worth).
So we have a bunch of protected methods, and they all need testing.
While you could test them in the same file you test your actions, thematically they are very different, and I think it makes more sense to put them in their own file. Here is an example. The only tricky part is that you need to say what controller it should use with the "tests" command. Oh, and you need to use "send" to access the method being tested, as it is protected.
require 'test/test_helper'
class ControllerMethodsTest < ActionController::TestCase
tests PostsController
def setup
user_setup
end
def test_current_user
login_as ['trainer', 'it'], request
assert_equal 'tester', @controller.send(:current_user).login
end
end
The "user_setup" methods puts some roles into the testing database. The "login_as" method is one that I have used a lot for testing actions relating to web pages that have the user logged in.
def login_as roles, request
create_user
user = UserLog::User.find_by_login 'tester'
roles = [roles] unless roles.is_a? Array
roles.each { |role| assign_role user, role }
request.session[:user_id] = user.id
#p "set request.session[:user_id] to #{request.session[:user_id]}"
end
def create_user name = "tester"
user = UserLog::User.new
user.login = name
user.email = "#{name}@domain.com"
user.username = name.titlecase
user.password = "12345678"
user.password_confirmation = "12345678"
user.save(:validate => false)
user.send(:activate!)
UserLog::User.find_by_login name
end
def assign_role(user, rolename)
role = UserLog::Role.find_by_rolename(rolename)
raise "Failed to find role #{rolename}" if role.nil?
permission = UserLog::Permission.new
permission.role = role
permission.user = user
permission.save(:validate => false)
end
See part 2 here.