我有一个Perl模块,我声明了一些常量:
use constant BASE_PATH => "/data/monitor/";
在实时操作中,常量永远不会改变,但我希望能够修改它 在我的单元测试中,例如将其设置为 〜/ project / testdata / 。有没有办法做到这一点 不必使用“非常数”?
我可以在constant.pm上使用 Test :: MockObject 吗?
答案 0 :(得分:6)
当使用常量时,它们被实现为常量函数,其行为类似于:
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";
虽然你为什么要这样做但我不太确定。
答案 1 :(得分:6)
测试经常揭示设计的不灵活性。这是其中一次。那个常数不应该是恒定的。
如果你出于性能原因这样做,我愿意用坚硬的货币押注它没有任何区别。
答案 2 :(得分:3)
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
的作者,但是我遇到了同样的问题。
答案 3 :(得分:2)
package My::Class; use constant BASE_PATH => "/a/real/value/"; # ..more code here.. 1;
现在进行单元测试:
use My::Class; *{My::Class::BASE_PATH} = sub { "/a/fake/value" }; # do your tests here...
答案 4 :(得分:1)
显然,如果您的测试确实改变了它,那么您的BASE_PATH定义被用于/编译到另一个子例程中(通过
*BASE_PATH = sub { ... }
或其他东西)你没有解决方案(因为当原始模块使用BASE_PATH作为常量时,它确实定义了一个INLINE函数,当在其他代码中使用时,它已内联)