2015-01-27 2 views
0

Я пытаюсь построить удобный класс насмешливый, используя Moops:Generic трассировка фиктивный класс

#!/usr/bin/env perl 
use Modern::Perl '2014'; 
use Moops; 
use Test::More; 

class aClass { 
    method m {} 
    method l {} 
}; 

class NotWorkingMockAClass 
extends aClass { 

    has methodCallLog => (
    is => 'rw', 
    default => sub { [] }, 
    isa  => ArrayRef 
); 

    around m, l { 
    push $self->methodCallLog, (caller(0))[3] =~ m/::(\w+)$/; 
    $next->($self, @_); 
    } 

}; 

my $mac = NotWorkingMockAClass->new(); 
$mac->m(); 
$mac->l(); 
$mac->m(); 

is(($mac->methodCallLog)->[0], 'm', 'mcl[0] == m'); 
is(($mac->methodCallLog)->[1], 'l', 'mcl[1] == l'); 
is(($mac->methodCallLog)->[2], 'm', 'mcl[2] == m'); 

Это дает:

$ perl mocking.pl 
ok 1 - mcl[0] == m 
not ok 2 - mcl[1] == l 
# Failed test 'mcl[1] == l' 
# at mocking.pl line 33. 
#   got: 'm' 
#  expected: 'l' 
ok 3 - mcl[2] == m 

Таким образом, проблема, кажется,, что caller() всегда возвращает m, когда я использую ярлык around m,l ...

Определение класса следующим образом:

class WorkingMockAClass 
extends aClass { 

    has methodCallLog => (
    is => 'rw', 
    default => sub { [] }, 
    isa  => ArrayRef 
); 

    method _logAndDispatch(CodeRef $next, ArrayRef $args){ 
    push $self->methodCallLog, (caller(1))[3] =~ m/::(\w)$/; 
    $next->($self, @$args); 
    } 
    around m { 
    $self->_logAndDispatch($next, \@_); 
    } 

    around l { 
    $self->_logAndDispatch($next, \@_); 
    } 
}; 

работает, но немного более многословным и громоздким писать.

Есть ли лучший способ добиться чего-то подобного с помощью Moops?

ответ

2

Лично Moops или иначе, я бы не доверял caller в любом методе, потенциально имеющем модификаторы, применяемые к нему. Я также не доверяю этим модификаторам. Вы слишком полагаетесь на внутренности того, как работают модификаторы методов. (Который будет отличаться между Moo/Moose/Mouse.)

Вы пробовали что-то вроде этого?

push @{ $self->methodCallLog }, Sub::Identify::sub_name($next); 

(Или использовать Sub :: Util вместо Sub :: Выявить.)

+0

'Sub :: Identify' работает как шарм. Думая дальше в сторону общности: видите ли вы способ выражения чего-то вроде 'around * {}'? Который может быть помещен в роль, позволяя что-то вроде 'aTracingClass расширяет aClass с помощью Tracing'? – sschober

+0

Не решение Moops, но вы можете попробовать MooseX :: RoleQR. Он позволяет 'around qr/regexp/=> sub {...}' работать в ролях. (Муз уже позволяет работать в классах, а не в ролях). – tobyink

Смежные вопросы