|
|
Choosing A Webhost: |
Re: [Boston.pm] overriding instance methods, dynamic package namespaces: msg#00028lang.perl.perl-mongers.boston
http://search.cpan.org/~stevan/Class-MOP-0.37/ ---------- Forwarded message ---------- From: Guillermo Roditi <groditi-Re5JQEeQqe8AvxtiuMwx3w@xxxxxxxxxxxxxxxx> Date: May 18, 2007 10:20 AM Subject: Re: [Boston.pm] overriding instance methods, dynamic package namespaces To: Tom Metro <pm-5a1Jt6qxUNc@xxxxxxxxxxxxxxxx> 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 <pm-5a1Jt6qxUNc@xxxxxxxxxxxxxxxx> 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 > Boston-pm-PqP1ghmmPMdAfugRpC6u6w@xxxxxxxxxxxxxxxx > http://mail.pm.org/mailman/listinfo/boston-pm >
|
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | Re: [Boston.pm] overriding instance methods, dynamic package namespaces, Ben Tilly |
|---|---|
| Next by Date: | Re: [Boston.pm] overriding instance methods, dynamic package namespaces, Uri Guttman |
| Previous by Thread: | Re: [Boston.pm] overriding instance methods, dynamic package namespaces, Uri Guttman |
| Next by Thread: | Re: [Boston.pm] overriding instance methods, dynamic package namespaces, Tom Metro |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
Free MagazinesCisco NewsReceive a free quarterly e-newsletter with exclusive articles on how Cisco IT uses its own products and solutions to enable the business. subscribe Systems Management News, the newspaper for IT systems administration and data center managers! Each issue of Systems Management News is chock-full of news and analysis to help you understand what's happening in your field. subscribe The Enterprise Newsweekly eWeek is the essential technology information source for builders of e-business. subscribe Oracle Magazine Oracle Magazine contains technology strategy articles, sample code, tips, Oracle and partner news, how to articles for developers and DBAs, and more. Oracle (NASDAQ: ORCL) is the world's largest enterprise software company. subscribe Total Telecom Total Telecom is "The Economist of the communications industry". subscribe |