[Catalyst] getting $c in model unit test

John Napiorkowski jjn1056 at yahoo.com
Tue May 15 15:49:21 GMT 2007


--- Nathan Gray <kolibrie at graystudios.org> wrote:

> I would like to test a model with a unit test. 
> Catalyst kindly
> generates stub unit tests for models, but it does
> not include a stub
> showing how to instantiate the context object.
> 
> I have looked at:
> 
>   -
>
http://dev.catalystframework.org/wiki/Testing#ModelTests
>     (Examples of test for your model: STUB)
>   -
>
http://search.cpan.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Tutorial/Testing.pod
>     (TIP: For unit tests vs. the "full application
> tests" approach used
>   by Test::WWW::Mechanize::Catalyst, see
> Catalyst::Test.)
>   -
> http://search.cpan.org/perldoc?Catalyst%3A%3ATest
>     (METHODS: get request local_request
> remote_request)
>   -
> http://search.cpan.org/perldoc?Catalyst%3A%3ADevel
>     (The documentation remains with
> Catalyst::Runtime.)
>   -
> http://search.cpan.org/perldoc?Catalyst%3A%3ARuntime
>     ($c->prepare( @arguments ) Creates a Catalyst
> context from an engine-specific request (Apache,
> CGI, etc.).)
> 
> Does anyone have an example unit test that has
> access to $c?
> 
> Thanks so much!
> 
> -kolibrie

Hi,

I'm assuming that what you mean is that you want to
test the model without running catalyst as it's
container.  I'm not sure there is a good way to do
this.   What I usually do is make my model a stand
alone perl class that can be tested individually and
then have a thin Catalyst model that wraps and
provides it to my webapp.

For things that would normally go into the catalyst
context, like say $c->user, I try to not access this
in my model directly.  Instead I wrap it in an adapter
class, that gets generated via a factory interface. 
That way I can create versions of this class that can
live outside of catalyst.

So something like:

MyApp::User  is a base User Class
MyApp::CatalystUser  creates a User from $c->user
MyApp::StandaloneUser  creates a user from params

MyApp::UserFactory  returns a MyApp::User based on
what you have

MyApp::WelcomeEmailUser  Expects a User class and
sends a welcome email

MyApp::Web::Model::User  A catalylst model that wraps
the UserFactory for you.

So MyApp::Web::Model::User might do something like

__PACKAGE__->mk_accessors(qw/user/);

sub ACCEPT_CONTEXT
{
 my ( $self, $c ) = @_;
 my $user = MyApp::UserFactory->create($c->user);

 $self->user($user);
 return $self;
}

and in a catalyst controller you do:

my $user = $c->model('User')->user;
MyApp::WelcomeEmailUser->mail($user);

While in your unit test you can:

my $user = MyApp::UserFactory->create({
  name=>"xxxxx",
  email=>"asdas at email.com",
});

my $email_status =
MyApp::WelcomeEmailUser->mail($user);



There's probably an easier and more concise way to do
this but right this minute I'm still on my first
coffee of the day.  Hopefully some smarter people will
chime in and correct me.

--john

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 



More information about the Catalyst mailing list