我有一个非常简单的脚本,该脚本使用Test::MockTime模拟时间,但是time调用的输出在代码的两部分中有所不同。
这是脚本:

package mocker;

use strict;
use warnings;

sub abcd {
    print "in abcd, time is " . time . "\n";
}

BEGIN {
    use Test::MockTime qw(set_absolute_time restore_time);
    set_absolute_time(0);
};

sub do_mock {
    print "Current epoch in do_mock is: " . time . "\n";
    abcd;
    restore_time();
}

1;

我在脚本中调用mocker::do_mock:
use strict;
use warnings;

use mocker;

mocker::do_mock;

我期望两个打印语句中的当前时间输出都为“0”,但奇怪的是,我有以下输出:
Current epoch in do_mock is: 0
in abcd, time is 1450343385

那么,为什么abcd时间恢复为当前时间?

最佳答案

Test::MockTime的documentation解释说:“它在编译时覆盖localtimegmtimetime 。”所以:

print "Before: " . time; # Uses CORE::time()

use Test::MockTime;      # Override time()

print "After: " . time;  # Uses overridden time()

您可以使用B::Deparse看到它:
$ perl -MO=Deparse foo
print 'Before: ' . time;
use Test::MockTime;
print 'After: ' . &CORE::GLOBAL::time();
foo syntax OK

time()的第二次调用实际上使用CORE::GLOBAL::time(),它是被覆盖的版本。

要解决此问题,请在调用time()之前确保已编译Test::MockTime:
package mocker;

use strict;
use warnings;

use Test::MockTime qw(set_absolute_time restore_time);

sub abcd {
    print "in abcd, time is " . time . "\n";
}

BEGIN {
    set_absolute_time(0);
};

sub do_mock {
    print "Current epoch in do_mock is: " . time . "\n";
    abcd;
    restore_time();
}

1;

10-01 20:59