【发布时间】:2014-02-13 14:21:39
【问题描述】:
我正在尝试对模块进行单元测试。我需要帮助和信息,如何模拟或存根子例程来测试包。
我不想使用我在cpan.遇到的模块
【问题讨论】:
我正在尝试对模块进行单元测试。我需要帮助和信息,如何模拟或存根子例程来测试包。
我不想使用我在cpan.遇到的模块
【问题讨论】:
您可以通过在测试中以下列方式覆盖它们来模拟潜艇:
no warnings;
local *Foo::bar = sub {
# do stuff
};
use warnings;
您通常希望设置一个变量,以便稍后在您的模拟中的测试中检查。
(即使我建议使用 Test::MockModule,但您明确指定不使用它)
【讨论】:
很难说出您可能需要解决哪些条件,因为您没有提供太多细节。因此,这是对模拟子例程所涉及内容的一般概述。
Perl 将包子例程存储在符号表中,我们可以通过"globs" 访问它。以包Some::Package 中的子程序do_the_thing 为例,您分配给符号 *Some::Package::do_the_thing 的最后一个子程序将替换该子程序的正常功能。我们也可以检索它,以便我们可以调用它。
my $do_the_original_thing = *Some::Package::do_the_thing{CODE};
请注意,要访问它,我们必须告诉它访问 glob 的 CODE 插槽。要更换潜艇,我们没有。 Perl 知道将代码引用分配给 glob 的 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];
}
【讨论】: