Трудно сказать, какие условия вы, возможно, придется работать вокруг, потому что вы не даете много деталей. Итак, это общий обзор того, что связано с насмешками подпрограмм.
Perl хранит подпрограммы пакета в таблице символов, с которой мы можем получить доступ через "globs". Возьмите подпрограмму do_the_thing
в пакете Some::Package
, последнюю подпрограмму, которую вы назначаете на символ .*Some::Package::do_the_thing
заменит нормальную функциональность этого юнита. Мы также можем получить его, чтобы мы могли позвонить ему.
my $do_the_original_thing = *Some::Package::do_the_thing{CODE};
Обратите внимание, что для доступа к нему, мы должны сказать ему, чтобы получить доступ к CODE
слот в Glob. Чтобы заменить суб, мы этого не сделаем. Perl знает, как назначить код ref для слота CODE глобуса.
*Some::Package::do_the_thing = sub {
if ($_[0] eq '-reallyreallydoit' and $_[1]) {
shift; shift;
goto &$do_the_original_thing; # this does not return here
}
# do the mock thing
...
};
Примечание: Путь показан демонстрирует минимальный способ вызова процедуры, так он действует так же, как процедуры вы насмешливый. Если вам не нравится goto
, то это делает то же самое:
#goto &$do_the_original_thing; # this does not return here
return &$do_the_original_thing; # this returns here...to return
Однако, если вы хотите проверить, что было возвращено, или сохранить его для создания будущих тестов, вы могли бы просто сделать это следующим образом:
my $future_test_value ;
*Some::Package::do_the_thing = sub {
if ($_[0] eq '-reallyreallydoit' and $_[1]) {
shift; shift;
my @res;
if (wantarray) {
@res = &$do_the_original_thing;
}
elsif (!(wantarray // 1)) {
$res[0] = &$do_the_original_thing;
}
$future_test_value = $res[0];
return wantarray ? @res : $res[0];
}
Это на самом деле хорошо. Но есть ли способ использовать это без инструкции goto? – ganezdragon
@ganezdragon см. Правки. – Axeman