Thursday, December 14, 2006

Functional Testing in Rails that Requires Login

For RESTful authentication, there is a
login_as(user) method in AuthenticatedTestHelper module that sets the
current user
in the session from the user fixtures. This is under the lib directory.

In my functional test, I have:

def test_should_show_billing_profile_for_valid_login
login_as (:aaron)
get :show, :id => :aaron.id
assert_response :success
assert_select "html:root>head>title", "BillingProfiles: show"
end

users.yml looks like this:

quentin:
id: 1
login: quentin
email: quentin@example.com
salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test
created_at: <%= 5.days.ago.to_s :db %>
aaron:
id: 2
login: aaron
email: aaron@example.com
salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test
created_at: <%= 1.days.ago.to_s :db %>


class BillingProfilesController < ApplicationController

before_filter :login_required

def show
@user = User.find(session[:user], :include => [:billing_profile])
@billing_profile = @user.billing_profile

respond_to do |format|
format.html # show.rhtml
format.xml { render :xml => @billing_profile.to_xml }
end
end

The problem was that I was using session[:user_id] in my controller
whereas the RESTful authentication
module is using session[:user] as shown below:

module AuthenticatedTestHelper
# Sets the current user in the session from the user fixtures.
def login_as(user)
@request.session[:user] = user ? users(user).id : nil
end
....

So I changed my controller code to use session[:user] and my tests now
pass! The plugin itself has the API to help you do the functional
testing. Very nice indeed.

2 comments:

  1. Storing objects inside your sessions can sometimes cause data inconsistency problems. First problem is that you need to be sure to update your session object when any changes occur to that object. Its easy enough to make sure you do that in this situation though. The second problem is when there are multiple people updating db records and you rely on your session object rather than pulling the data from the db. Someone else could have modified that data and you rely on it in your session.

    Not to mention added memory usage because now you're storing your password hashes also in memory. I prefer to either store just the id or the username in the session. Sorry about the ramble.

    ReplyDelete
  2. Brian,
    From what I know of that plugin, the session object is called player, but it is actually just the ID.

    ReplyDelete