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.