繁体   English   中英

在perl中存根并模拟subrotine以进行单元测试

[英]stub and mock a subrotine for unit testing in perl

我正在尝试对该模块进行单元测试。 我需要帮助和信息,如何模拟或添加子例程来测试程序包。

我不想使用在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];
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM