# Functional testing with logging in

**URL:** <https://www.ruby-forum.com/t/functional-testing-with-logging-in/108253>\
**Category:** Rails\
**Created:** [July 1, 2007, 2:32am UTC](https://www.ruby-forum.com/t/functional-testing-with-logging-in/108253 "2007-07-01T02:32:30Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![surge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@surge](https://www.ruby-forum.com/u/surge)\
**Post date:** [July 1, 2007, 2:32am UTC](https://www.ruby-forum.com/t/functional-testing-with-logging-in/108253/1 "2007-07-01T02:32:30Z")

</div>

Hello,

One of the actions in one of my controllers requires a login and I’m  
trying to write a test for that action. I don’t want to actually go  
through the login process. I just want to initialize a session  
variable and be done with it 🙂

So, the way the authentication works is pretty simple. In my  
application controller I defined this method:

def authenticate  
if session[:user].nil?  
session[:initial\_uri] = request.request\_uri  
redirect\_to :controller =\> ‘user’, :action =\> ‘login’  
end  
end

In the controller, I have :before\_filter = “authenticate”

Now, my test so far is:

def test\_show\_valid\_request

# Assign the user session variable the user with id = 1

```
@request.session[:user] = User.find(1)

```

# Santity test – this does say that the value is an ActiveRecord

object.  
puts @request.session[:user]

```
# Try to call the action, which triggers a call to authenticate
get :show, { :id => '1' }, { :customer_id => '16' }

# This should fail because no redirection should take place
assert_redirect_to(:controller => 'user', :action => 'login')

```

end

What happens is that the “if session[:user]” in “authenticate” returns  
nil.

tail -f on logs/test.log has "Session ID: ", which would mean that no  
session exists?

Anybody know what I’m missing?

---

<div class="post-metadata">

**Author:** ![surge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@surge](https://www.ruby-forum.com/u/surge)\
**Post date:** [July 1, 2007, 1:40pm UTC](https://www.ruby-forum.com/t/functional-testing-with-logging-in/108253/2 "2007-07-01T13:40:14Z")

</div>

On 7/1/07, surge [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> application controller I defined this method:  
> Now, my test so far is:  
> get :show, { :id =\> ‘1’ }, { :customer\_id =\> ‘16’ }
> 
> Anybody know what I’m missing?

Because your using a before filter, and the session variable is set  
there is  
not actually anything being evaluated for the method. Hence the last  
evaluated expression for the method is nil.

If at the end you returned the session[:user] it should work.

def authenticate  
if session[:user].nil?  
session[:initial\_uri] = request.request\_uri  
redirect\_to :controller =\> ‘user’, :action =\> ‘login’  
end  
session[:user]  
end

There are dangers associated with storing your user object in the  
session.  
Stale objects and more. There is plenty of discussion about it on the  
list  
and elsewhere. It is common practice to just store the ID of the user  
object in the session and then do a lazy lookup of the user when you  
need  
it. It only results in one lookup per request for the user object.

eg something like

def current\_user  
@current\_user ||= User.find\_by\_id( session[:user\_id] ) if  
session[:user\_id]  
end

HTH  
Daniel

---

<div class="post-metadata">

**Author:** ![surge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@surge](https://www.ruby-forum.com/u/surge)\
**Post date:** [July 1, 2007, 3:08pm UTC](https://www.ruby-forum.com/t/functional-testing-with-logging-in/108253/3 "2007-07-01T15:08:23Z")

</div>

> Because your using a before filter, and the session variable is set there is  
> not actually anything being evaluated for the method. Hence the last  
> evaluated expression for the method is nil.

Hmm, I don’t think that’s it because I’m not relying on the return of  
value of “authenticate”. It just redirects or doesn’t. And it does  
redirect, which means that session[:user] is nil by the time  
authenticate is called. But if I do this:

get :show, { :id =\> ‘1’ }, { :user =\> User.find(1) }

it does work. So, for some reason if the session variable is set as  
part of the get call, it works.

> There are dangers associated with storing your user object in the session. Stale objects and more.

Thanks for the tip. I’ll rework my process to take that into account.  
Never thought about it!

Thanks for the post, Daniel.

---

<div class="post-metadata">

**Author:** ![surge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@surge](https://www.ruby-forum.com/u/surge)\
**Post date:** [July 1, 2007, 6:20pm UTC](https://www.ruby-forum.com/t/functional-testing-with-logging-in/108253/4 "2007-07-01T18:20:45Z")

</div>

> Can you see that in your situation, when your session variable is set the method will return nil?

If I do @request.session[:user\_id] = 1, the “if session[:user].nil?”  
returns true and the redirect does happen.  
If I do get :show, { :id =\> ‘1’ }, { :customer\_id =\> ‘16’ }, the  
method does return nil, but the action of the controller is not  
stopped.

That’s interesting about halting the action of a controller. It’s  
strange though. Say I do return false from a before filter, what would  
the user see?

I’m not a big expert on all this – just reporting the results.

Sergei

---

<div class="post-metadata">

**Author:** ![surge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@surge](https://www.ruby-forum.com/u/surge)\
**Post date:** [July 1, 2007, 8:05pm UTC](https://www.ruby-forum.com/t/functional-testing-with-logging-in/108253/5 "2007-07-01T20:05:58Z")

</div>

There is a better way (IMO). Move as much authentication as possible  
into your model, then create a logged\_in? helper function in your  
application.rb. For your tests, use Mocha (http://  
[mocha.rubyforge.org/](http://mocha.rubyforge.org/)) and stub the logged\_in? function to return true  
for tests where the user is meant to be logged in and false for ones  
where you might have a bogus user.

E.g.,

# your controller

def test\_user\_is\_logged\_in  
controller.stubs(:logged\_in?).returns(true)

# …

end

Just a thought…

On Jul 1, 2007, at 9:19 AM, surge wrote:

> That’s interesting about halting the action of a controller. It’s
> 
> >

Steve R.  
removed\_email\_address@domain.invalid  
[http://www.calicowebdev.com](http://www.calicowebdev.com)

---

<div class="post-metadata">

**Author:** ![surge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@surge](https://www.ruby-forum.com/u/surge)\
**Post date:** [July 1, 2007, 3:57pm UTC](https://www.ruby-forum.com/t/functional-testing-with-logging-in/108253/6 "2007-07-01T15:57:27Z")

</div>

On 7/1/07, surge [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> authenticate is called. But if I do this:  
> Never thought about it!
> 
> Thanks for the post, Daniel.

In IRB

?\> def test

> > if @test.nil?  
> > “Blah”  
> > end  
> > end  
> > =\> nil  
> > test  
> > =\> “Blah” # =\> When @test is not set the method returns a value  
> > @test = “I’m Set”  
> > =\> “I’m Set”  
> > test  
> > =\> nil #=\> When @test is set the method returns nil

Can you see that in your situation, when your session variable is set  
the  
method will return nil?

From the docs you can see.  
[http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html](http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html)

before\_filter[http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000180](http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000180)and  
around\_filter[http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000186](http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000186)may  
halt the request before controller action is run. This is useful, for  
example, to deny access to unauthenticated users or to redirect from  
http to  
https. Simply return false from the filter or call render or redirect.

So if the result of a method evaluates to false ( either false or nil )  
then  
the action of the controller will not be run. Since your redirect\_to is  
inside an if statement whose body is never executed it does not  
re-direct  
either. So even though you aren’t explicitly relying on the return  
value  
of authenticate, rails is as part of the before\_filter behavior.

I’ve never actually tried this. What is returned in this situation?

Daniel

---

<div class="post-metadata">

**Author:** ![surge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@surge](https://www.ruby-forum.com/u/surge)\
**Post date:** [July 1, 2007, 8:53pm UTC](https://www.ruby-forum.com/t/functional-testing-with-logging-in/108253/7 "2007-07-01T20:53:04Z")

</div>

Steve, thanks for the idea. Right now though I want to stick to the  
framework so I can keep the amount of new information to a minimum 🙂

---

<div class="post-metadata">

**Author:** ![surge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@surge](https://www.ruby-forum.com/u/surge)\
**Post date:** [July 1, 2007, 9:11pm UTC](https://www.ruby-forum.com/t/functional-testing-with-logging-in/108253/8 "2007-07-01T21:11:07Z")

</div>

Here is some code from one of my older projects:

# in controller

def test\_admin  
get\_logged\_in  
get :admin  
assert\_response :success  
end

# in test\_helper.rb

def get\_logged\_in  
request.session[:user] = users(:users\_004).id  
# theoretically, there is more involved in getting logged in…  
i.e., login time  
end

Hope this helps.

On Jul 1, 2007, at 11:51 AM, surge wrote:

> > where you might have a bogus user.
> > 
> > > returns true and the redirect does happen.
> > 
> > > Sergei
> > 
> > Steve R.  
> > removed\_email\_address@domain.invalid://www.calicowebdev.com
> 
> >

Steve R.  
removed\_email\_address@domain.invalid  
[http://www.calicowebdev.com](http://www.calicowebdev.com)

---

<div class="post-metadata">

**Author:** ![surge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@surge](https://www.ruby-forum.com/u/surge)\
**Post date:** [July 2, 2007, 1:13am UTC](https://www.ruby-forum.com/t/functional-testing-with-logging-in/108253/9 "2007-07-02T01:13:29Z")

</div>

Yes, that’s what I was doing too – except are you sure it’s  
“request.session[:user] = users(:users\_004).id” and not  
“@request.session[:user] = users(:users\_004).id”? Because otherwise I  
get “an unknown local variable”. Anyways, this general approach is not  
working for me for some reason. But I’m OK with passing the session  
variables along with the call to “get”

Thanks!  
Sergei
