[英]stub and mock a subrotine for unit testing in perl
You an mock subs by overriding them in the following way in your test: 通过在测试中按以下方式覆盖它们,可以创建模拟子:
no warnings;
local *Foo::bar = sub {
# do stuff
};
use warnings;
You typically want to set a variable to be checked later in your test inside your mock. 您通常希望设置一个变量,以便稍后在模拟中的测试中进行检查。
(even if I suggest using Test::MockModule, but you explicitly specified to not use it) (即使我建议使用Test :: MockModule,但您明确指定不使用它)
It's hard to tell what conditions you might have to work around, because you don't give much detail. 很难说出您可能需要解决的条件,因为您没有提供太多细节。 So this is a general overview of what's involved in mocking subroutines.
因此,这是模拟子例程中涉及的内容的一般概述。
Perl stores package subroutines in the symbol table which we can access through "globs" . Perl将包子例程存储在符号表中,我们可以通过“ globs”访问它们。 Take the subroutine
do_the_thing
in package Some::Package
, the last subroutine you assign to the symbol *Some::Package::do_the_thing
will replace the normal functionality of that sub. 将程序包
Some::Package
的子例程do_the_thing
分配给符号 *Some::Package::do_the_thing
的最后一个子程序,它将替换该子程序的常规功能。 We can also retrieve it so we can have it to call. 我们也可以检索它,以便调用它。
my $do_the_original_thing = *Some::Package::do_the_thing{CODE};
Note that to access it, we have to tell it to access the CODE
slot of the glob. 请注意,要访问它,我们必须告诉它访问glob的
CODE
插槽。 To replace the sub, we don't. 要替换潜水艇,我们不需要。 Perl knows to assign code refs to the CODE slot of the glob.
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
...
};
NOTE: The way shown demonstrates a minimal way to call a procedure so it acts just like the procedure you're mocking. 注意:所示方式演示了一种最小的方法调用过程,因此它的行为就像您要模拟的过程一样 。 If you don't like
goto
, then this does the same thing: 如果您不喜欢
goto
,那么它会做同样的事情:
#goto &$do_the_original_thing; # this does not return here
return &$do_the_original_thing; # this returns here...to return
However, if you want to test what was returned, or store it to set up future tests, you could simply do it like this: 但是,如果要测试返回的内容,或存储它以设置将来的测试,则可以像这样简单地进行操作:
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];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.