Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

Re: Testing -- making a new constructor behave differently for one package

by tobyink (Abbot)
on Jan 28, 2012 at 13:39 UTC ( #950514=note: print w/replies, xml ) Need Help??

in reply to Testing -- making a new constructor behave differently for one package

Given that you're already using Moose, which has method modifiers, don't mess around with rubbish like this:

no warnings 'redefine'; *Foo::real_new = \&Foo::new; *Foo::new = sub { if (caller() eq 'Bar') { print "Returning real Foo.\n"; return Foo->real_new; } print "Returning fake Foo.\n"; return FakeFoo->new; };

Use the features of your framework:

{ package Foo; use Moose; around new => sub { my ($orig, $class, @args) = @_; if (caller() eq 'Bar') { print "Returning real Foo.\n"; return $class->$orig(@args); } print "Returning fake Foo.\n"; return FakeFoo->new(@args); }; }

Be aware that putting method modifiers on new can interfere with class immutability, so avoid doing this in production code. It should work fine for testing though.

(Also be aware that the call stack can have various Moosey things in it when you use method modifiers. So checking caller() might not be enough - you might need to walk up the call stack a little.)

Replies are listed 'Best First'.
Re^2: Testing -- making a new constructor behave differently for one package
by tj_thompson (Monk) on Jan 30, 2012 at 18:58 UTC

    Yeah, but that assumes that when you're designing Foo you want to hard code this test hook into the class. This seems like a bad plan for a number of reasons. Problem here is you need to test Foo after it's been created.

    I actually tried to figure out how to add a method modifier from the Foo meta class so it only existed during my test case, but couldn't quite figure how to do that this was my plan B...but I eventually went to plan C after realizing (thanks Chromatic) I could hijack the accessor to the class name. That turned out to be far simpler :)

      Why does it assume that? The around new => sub {}; stuff doesn't need to be in the same file where the Foo class is defined. I'd probably put it in the ".t" file.

        That actually never occurred to me. Excellent point and it would have been another way to accomplish my objective. Thanks for the insight.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://950514]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (5)
As of 2018-01-18 13:01 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (211 votes). Check out past polls.