Please take our Survey
logo       

Choosing A Webhost:
A web hosting service is a type of Internet hosting service that allows individuals and organizations to provide their own website accessible via the World Wide Web. Web hosts are companies that provide space on a server they own for use by their clients as well as providing Internet connectivity, typically in a data center. Web hosts can also provide data center space and connectivity to the Internet for servers they do not own to be located in their data center, called colocation. more...

Re: [Boston.pm] overriding instance methods, dynamic package namespaces: msg#00022

lang.perl.perl-mongers.boston

Subject: Re: [Boston.pm] overriding instance methods, dynamic package namespaces

Evals and typeglobs will let you do it.

If you don't like that sort of thing (I don't),

you can use a module I wrote called SymbolTable

which hides all the ugliness for you.



http://backpan.cpan.org/authors/id/G/GS/GSLONDON/SymbolTable-0.02.readme

(paste)

SymbolTable - An easy interface to symbol tables ( no eval() and no typeglobs )

You can use SymbolTable to export subroutines, convert someone else's
package variable into a constant, change your own subroutines, and hack
and slash at perl's symbol table without a single call to eval and without
using a single typeglob.
(/paste)

You can then stub out method2 by assigning an empty sub to a hash key.

I'm pretty sure it still works.



Greg









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>
Google Custom Search

Recently Viewed:
qnx.openqnx.dev...    gcc.libstdc++.c...    solaris.opensol...    information-ret...    misc.misterhous...    web.catalyst.ge...    apache.webservi...    redhat.release....    hardware.lirc/2...    kernel.autofs/2...    technology.sust...    linux.vdr/2003-...    editors.lyx.gen...    org.user-groups...    netbsd.devel.pk...    xdg.devel/2004-...    version-control...    jakarta.slide.d...    debian.packages...    creativecommons...    ports.ppc.embed...    bug-tracking.bu...   
Home | blog view | USPTO Patent Archive | advertise | OSDir is an inevitable website. super tiny logo

Free Magazines

Cisco News
Receive 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