2017-08-28 3 views
4

Ich bin dabei, das Buch Intermediate Perl zu studieren.Testen der Filialzuweisung in Perl für SUPER :: Methoden

In Kapitel 18 Objekt Zerstörung wird die folgende DESTROY Methodendefinition eingeführt:

# 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"; 
    } 
# ... 
} 

Nach ein paar erfolglos versucht, schrieb ich diesen Test basierend auf 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'); 
} 

kann ich nicht testen die Ausgabe in beiden Fällen korrekt, da die Methodenredefinition sub Animal::DESTROY { undef } auch den Test im vorherigen Block beeinflusst.

Kennen Sie einen Weg, um sicherzustellen, dass die Methodenredefinition wie erwartet funktioniert?

Dank

+2

Wenn Sie die 'Tier: ein Tier Klasse und' Tier: ein Tier schreiben immer zusammen mit 'Pferd verwendet wird ', dann weißt du, dass' Animal' eine DESTROY-Methode anbietet - der '-> can ('SUPER :: DESTROY') Check wird etwas überflüssig. Ich würde einfach '$ self> SUPER :: DESTROY' direkt nennen. – amon

+3

Btw nicht die DESTROY-Methode in Ihren Tests auslösen, indem Sie es direkt aufrufen, dies könnte mehrere Male DESTROY aufrufen. Stattdessen "undef $ tv_horse", um die Variable zu löschen, die den Destruktor auslöst. – amon

+0

Ok, vielen Dank für den Hinweis – mabe02

Antwort

6

Diese bis zum Ende des umschließenden Blocks nur entfernt/neu definiert Unterprogramm gesetzt sollte,

{ 
    # not needed when removing method 
    # 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; 

    # .. 
} 
+0

Vielen Dank für Ihre schnelle Antwort. Diese Lösung funktioniert! "Devel: Cover" erkennt diesen Zweig jedoch nicht wie getestet: blib/lib/Horse.pm Zeile | % | Berichterstattung | Zweig 14 | 50 | T (grün) | F (rot) | if $ self> can ('SUPER :: DESTROY') – mabe02

+0

Soll 'DESTROY'' 'undef' zurückgeben oder' DESTROY' ganz entfernen? –

+2

@ mabe02 Um die Methode vollständig zu entfernen, lokalisiere einfach den Glob, ohne ein neues Sub zuzuweisen: 'local * Animal :: DESTROY;' wäre ausreichend. – amon

Verwandte Themen