8

我有一个 Perl 模块,我声明了一些常量:

use constant BASE_PATH => "/data/monitor/";

在实时操作中,常量永远不会改变,但我希望能够在我的单元测试中修改它,例如将其设置为~/project/testdata/. 有没有办法做到这一点而不必使用全局可变变量?

我可以Test::MockObject在 上使用constant吗?

4

5 回答 5

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";

尽管您为什么要这样做,但我不太确定。

于 2009-07-01T16:16:34.287 回答
5

测试经常揭示设计中的不灵活。这是其中之一。这个常数不应该是常数。

如果您出于性能原因这样做,我愿意用硬通货打赌它没有任何区别。

于 2009-07-03T07:51:39.150 回答
3
包我的::类;

使用常量 BASE_PATH => "/a/real/value/";

# ..更多代码在这里..

1个;

现在在您的单元测试中:

使用我的::类;
*{My::Class::BASE_PATH} = sub { "/a/fake/value" };

# 在这里做你的测试...
于 2009-07-02T23:26:13.547 回答
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,但我遇到了同样的问题。

于 2019-11-18T17:51:42.750 回答
1

显然,如果您对 BASE_PATH 的定义在您的测试确实更改之前使用/编译到另一个子例程中(通过

*BASE_PATH = sub { ... }

或其他东西)您没有解决方案(因为当原始模块使用 BASE_PATH 作为常量时,它确实定义了一个 INLINE 函数,该函数在其他代码中使用时是内联的)

于 2009-07-01T19:16:24.227 回答