Functional tests and protected actions


#1

Hello!

I have certain methods in my Application Controller, that I need to
access.
Namely ApplicationController#logged_in_user

The problem is, that when I try to access it, I get:

NoMethodError: protected method `logged_in_user’ called for
#

Any ideas how I can circumvent that?

Or are functional tests really not suited for any kind of logins and
session
work? I don’t see why I should move everything to a Integration Test
just
because I added user logins.

Any ideas?

Thanks,
Rob


#2

On Jun 6, 2006, at 02:28 AM, Robert MannI wrote:

I have certain methods in my Application Controller, that I need to
access. Namely ApplicationController#logged_in_user

The problem is, that when I try to access it, I get:

NoMethodError: protected method `logged_in_user’ called for
#

Any ideas how I can circumvent that?

The simplest way of dealing with this is to have your private/
protected controller methods only set instance variable values. That
way, you can run an assert on the value from within the context of
calling testing a public controller action/method.

However, given that what you are looking to test is a method of your
Application Controller, my guess is that you are calling it via a
before_filter. If that’s the case, then what you are probably going
to need to do is rely on the session object. If you look at my other
post on functional tests you’ll see how you can set session values
when you call into your controller actions.

Or are functional tests really not suited for any kind of logins
and session work? I don’t see why I should move everything to a
Integration Test just because I added user logins.

Integration tests are for testing the browser process across multiple
actions and controllers. Basically, you can use Integration tests to
completely verify your user stories, front to back. However, if you
haven’t already verified your business logic (ie. Models) with Unit
tests and your individual controller actions with Functional tests,
moving up to Integration tests would be a mistake…

-Brian


#3

On Jun 5, 2006, at 11:28 PM, Robert MannI wrote:

Any ideas how I can circumvent that?

protected unless $TESTING

set $TESTING to true in your test case.


Eric H. - removed_email_address@domain.invalid - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com


#4

Brian H.: I like to rely on my getters and setters. I don’t want to
know
how my class behaves, I just want to use it

Eric H.: I don’t like the idea of changing my code for the tests

I’ll might just change the protected property dynamically, just for the
duration of the tests.


#5

On Jun 8, 2006, at 04:19 PM, Robert MannI wrote:

Brian H.: I like to rely on my getters and setters. I don’t
want to know how my class behaves, I just want to use it

I’m not sure how to respond to this… at what point did I tell you
to not rely on your “getters and setters”?

As for how your class might behave, if you are looking to unit test
that class, I would think you’d absolutely want to know how it works.
Obviously, that need usually goes away when you are accessing that
class from outside of itself.

-Brian


#6

On 6-jun-2006, at 8:28, Robert MannI wrote:

Any ideas how I can circumvent that?

Or are functional tests really not suited for any kind of logins
and session work? I don’t see why I should move everything to a
Integration Test just because I added user logins. ]

Looks like you really want a publci method instead of a protected one.

def get_stuff
# do foo
end

hide_action :get_stuff

This will make it a public method and not a callable action. Another
option would be to just use send to override the access.

@controller.send :logged_in_user # bla bla bla

However, if you want t manage authentication in your tests, it’s a
much better idea to actually make your test go through authentication
all by itself, I do it with this method in my test case:

def with_user(slug, &block)
passwords = { :john => ‘secret’ }
begin
if @request
@previous_host = @request.host
@request.host = “#{slug}…mydomain.net”
with_http_auth(slug, passwords[slug.to_sym]) do
yield
end
else
yield
end
ensure # Sometimes the after_filter does not fire - if a
controller throws up, for instance, or the test throws
# do any cleanup here
@request.host = @previous_host if @request
end
end

Then, to test something with a specific user you do

get :index
assert_response 401

with_user :john do
get :index
assert_success
end

You can also make your method supply the actual User object to the
block to compare against it

with_user :john do | john |
get :index
assert_success
assert_equal assigns(:user), john
end


Julian ‘Julik’ Tarkhanov
please send all personal mail to
me at julik.nl