http://search.cpan.org/~stevan/Class-MOP-0.37/

---------- Forwarded message ----------
From: Guillermo Roditi <[EMAIL PROTECTED]>
Date: May 18, 2007 10:20 AM
Subject: Re: [Boston.pm] overriding instance methods, dynamic package
namespaces
To: Tom Metro <[EMAIL PROTECTED]>

Please take a look at Class::MOP and Class::MOP::Class. Sounds like a little
->meta foo would makeyour life easier... Introspection is good and good for
you!

On 5/17/07, Tom Metro <[EMAIL PROTECTED]> wrote:
>
> While writing unit tests for a module I ran across a few challenges...
>
> Given a module like:
>
> package Module::Under::Test;
>
> sub method1 {
>      ...
>      $self->method2( ... );
>      ...
> }
>
>
> To properly unit test this I want to replace method2 with a mock method
> so that I am only testing the actions of method1. The question is, how
> do you inject an overridden method2, aside from subclassing
> Module::Under::Test, which introduces other concerns (see below).
>
> What I'd ideally like to do is take an instantiated Module::Under::Test
> object, and dynamically remap that instance to point to a different
> method2. Something like:
>
>      my $mut = Module::Under::Test->new();
>      $mut->method2 = sub { ... };
>
> which of course wouldn't work. A typeglob could be used here:
>      *Module::Under::Test::method2 = sub { ... };
>
> but that alters the class, rather than the instance, and could impact
> other methods in the unit test. (I suppose one could save the current
> value and restore it later.)
>
> My understanding is that Perl's OO dereferencing for methods doesn't
> involve the object instance, other than to obtain the class name so it
> can find the right package namespace. If this is correct, then there
> probably isn't a way to do this other than subclassing.
>
> This kind of thing is easy to do in JavaScript:
>      var mut = new Module.Under.Test();
>      mut.method2 = function () { ... };
> but in JavaScript there aren't real classes - everything is an instance.
> Still, it'd be a shame to think JavaScript could do something Perl
> can't. :-)
>
>
>
> Another issue is how to simulate a "private" package namespace. For
> example, lets say you go the subclass route mentioned above, and in your
> test class create a test method like:
>
> sub test_method1 {
>      ...
>      {
>          package My::Module::Under::Test;
>          use base qw(Module::Under::Test);
>          sub method2 { ... }
>      }
>
>      my $mut = My::Module::Under::Test->new();
>      ...
> }
>
>
> While you can declare a package in this fashion, the
> My::Module::Under::Test package has global visibility. To minimize the
> possibility of conflicts with other similar subclasses declared in other
> test methods, you'd ideally want to do something like:
>
>          package __PACKAGE__::__SUB__::Module::Under::Test;
>
> But this doesn't work. As documented, __PACKAGE__ doesn't get
> interpolated. It has to be by itself. __SUB__, although I found
> references to it on Usenet, doesn't seem to actually exist.
>
> The easy solution here is to perform the substitution manually as you
> write the code, but it'd be nice if there was a more automated approach.
>
> It seems the only option is to do a string eval like:
>
>      my $PACKAGE = __PACKAGE__;
>      eval "package ${PACKAGE}::Module::Under::Test;" . q{
>          use base qw(Module::Under::Test);
>          sub method2 { ... }
>      };
>
> (Similarly caller() could be used to provide the equivalent of what the
> hypothetical __SUB__ would have provided.)
>
> Which works, but being a string eval this carries the down side of
> deferring syntax checking until run time, which is less than ideal.
>
> Maybe this would work:
>
>      {
>          eval "package " . __PACKAGE__ . "::Module::Under::Test;";
>          use base qw(Module::Under::Test);
>          sub method2 { ... }
>      }
>
> but I haven't tried it. I would expect not, as method2 will get added to
> the symbol table at compile time before the package namespace gets set.
>
> So does anyone know of hacks for dynamically generating a package
> namespace string?
>
> Is there any way to create an anonymous class? (Which is apparently
> possible in Java.) Given that everything has to end up in the global
> symbol table, I'm guessing not.
>
> Will any of this stuff be addressed in Perl 6?
>
>   -Tom
>
> --
> Tom Metro
> Venture Logic, Newton, MA, USA
> "Enterprise solutions through open source."
> Professional Profile: http://tmetro.venturelogic.com/
>
> _______________________________________________
> Boston-pm mailing list
> [email protected]
> http://mail.pm.org/mailman/listinfo/boston-pm
>
 
_______________________________________________
Boston-pm mailing list
[email protected]
http://mail.pm.org/mailman/listinfo/boston-pm

Reply via email to