我有一个 Perl 模块,我声明了一些常量:
use constant BASE_PATH => "/data/monitor/";
在实时操作中,常量永远不会改变,但我希望能够在我的单元测试中修改它,例如将其设置为~/project/testdata/
. 有没有办法做到这一点而不必使用全局可变变量?
我可以Test::MockObject
在 上使用constant
吗?
我有一个 Perl 模块,我声明了一些常量:
use constant BASE_PATH => "/data/monitor/";
在实时操作中,常量永远不会改变,但我希望能够在我的单元测试中修改它,例如将其设置为~/project/testdata/
. 有没有办法做到这一点而不必使用全局可变变量?
我可以Test::MockObject
在 上使用constant
吗?
当使用常量时,它们被实现为常量函数,行为如下:
use subs 'BASE_PATH';
sub BASE_PATH () {"/data/monitor/"}
程序中对 BASE_PATH 的任何使用都是内联的,因此无法修改。
为了达到类似的效果,您可以手动使用 subs pragma(使 BASE_PATH 表现为内置函数)并将 BASE_PATH 声明为标准函数:
use subs 'BASE_PATH';
sub BASE_PATH {"/data/monitor/"}
print "BASE_PATH is ".BASE_PATH."\n";
*BASE_PATH = sub {"/new/path"};
print "BASE_PATH is ".BASE_PATH."\n";
尽管您为什么要这样做,但我不太确定。
测试经常揭示设计中的不灵活。这是其中之一。这个常数不应该是常数。
如果您出于性能原因这样做,我愿意用硬通货打赌它没有任何区别。
包我的::类; 使用常量 BASE_PATH => "/a/real/value/"; # ..更多代码在这里.. 1个;
现在在您的单元测试中:
使用我的::类; *{My::Class::BASE_PATH} = sub { "/a/fake/value" }; # 在这里做你的测试...
unconstant
一种简单的方法是使用unconstant
.
# From ./lib/Foo.pm
package Foo {
use constant BASE_PATH => '/data/monitor/';
}
# From test.pl
use unconstant; # Do this first
use Foo;
use constant *Foo::BASE_PATH => '/otherData/otherMonitor/';
免责声明:我是 的作者unconstant
,但我遇到了同样的问题。
显然,如果您对 BASE_PATH 的定义在您的测试确实更改之前使用/编译到另一个子例程中(通过
*BASE_PATH = sub { ... }
或其他东西)您没有解决方案(因为当原始模块使用 BASE_PATH 作为常量时,它确实定义了一个 INLINE 函数,该函数在其他代码中使用时是内联的)