2017-08-28 10 views
4

Intermediate Perlの本を勉強しようとしています。章18 オブジェクト破壊SUPER ::メソッドのPerlでの分岐割り当てのテスト

は、以下のDESTROYメソッド定義を導入されています

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

数が失敗した試みの後、私は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'); 
} 

私がテストすることはできませんメソッドの再定義が前のブロックのテストにも影響を与えているため、両方の場合の出力が正しくなります。

メソッドの再定義が期待どおりに機能するようにする方法をご存知ですか?

おかげ

+2

をサブルーチンを再定義'、' - > can( 'SUPER :: DESTROY')チェックは少し不要になります。私は '$ self-> SUPER :: DESTROY'を直接呼び出しています。 – amon

+3

BtwテストでDESTROYメソッドを直接呼び出してトリガしないでください。DESTROYが複数回呼び出されることがあります。その代わりに、 'undef $ tv_horse'はデストラクタをトリガする変数をクリアします。 – amon

+0

アドバイスありがとうございました – mabe02

答えて

6

は、これは/削除設定する必要がありますが、 `Animal`クラスを書いていると` Animal`は常に馬 `と一緒に使用されている場合は、唯一のブロックを囲むの終わりまで

{ 
    # 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

あなたの素早い返答をありがとう。このソリューションは機能しています!しかし、 'Devel :: Cover'は、このブランチケースをテストしても検出しません。 blib/lib/Horse.pm line | %|カバレッジ|支店 14 | 50 | T(グリーン)| F(赤)| $ self-> can( 'SUPER :: DESTROY')の場合 – mabe02

+0

'DESTROY'が' undef'を返すか、 'DESTROY'を完全に削除しますか? –

+2

@ mabe02メソッドを完全に削除するには、新しいサブを割り当てずにglobをローカライズするだけです。 'local * Animal :: DESTROY;'で十分です。 – amon

関連する問題