mabe02 mabe02 - 2 months ago 20
Perl Question

Testing branch assignment in Perl for SUPER:: methods

I am about to finish to study the Intermediate Perl book.

In chapter 18 Object Destruction is introduced the following

DESTROY
method definition:

# lib/Animal.pm
package Animal {
# ...
sub DESTROY {
my $self = shift;
if ($self->{temp_filename}){
my $fh = $self->{temp_fh};
close $fh;
unlink $self->{temp_filename};
}
print '[', $self->name, " has died.]\n";
}
# ...
}

# lib/Horse.pm
package Horse {
use parent qw(Animal)
# ...
sub DESTROY {
my $self = shift;
$self->SUPER::DESTROY if $self->can( 'SUPER::DESTROY' );
print "[", $self->name, " has gone off to the glue factory.]\n";
}
# ...
}


After a few unsuccessfully attempt, I wrote this test based on this answer:

# t/Horse.t
#!perl -T

use strict;
use warnings;
use Test::More tests => 6;
use Test::Output;
# some other tests

# test DESTROY() when SUPER::DESTROY is not defined;
{
my $tv_horse = Horse->named('Mr. Ed');
stdout_is( sub { $tv_horse->DESTROY }, "[Mr. Ed has died.]\n[Mr. Ed has gone off to the glue factory.]\n",
'Horse DESTROY() when SUPER::DESTROY is defined');
}

{
my $tv_horse = Horse->named('Mr. Ed');
sub Animal::DESTROY { undef }
stdout_is( sub { $tv_horse->DESTROY }, "[Mr. Ed has gone off to the glue factory.]\n",
'Horse DESTROY() when SUPER::DESTROY is not defined');
}


I cannot test the output correctly for both cases since the method redefinition
sub Animal::DESTROY { undef }
is affecting also the test in the previous block.

Do you know any way to ensure the method redefinition to work as expected?

Thanks

Answer Source

This should set removed/redefined subroutine only until the end of enclosing block,

{
  no warnings 'redefine';

  my $tv_horse = Horse->named('Mr. Ed');
  # returns undef
  # local *Animal::DESTROY = sub { undef };

  # remove the mothod until end of the enclosing block
  local *Animal::DESTROY;

  # ..
}