1

这需要一些解释才能开始。我有一个单元测试,我使用Storable保存来自SOAP::WSDL的Class::Std::Fast::Storable对象。我存储的对象是 web 服务调用的结果。它最终用MIME::Base64编码并写入文件的某个位置。这很好用。

在构建单元测试时,我需要使用Test::MockObject来模拟对 web 服务的调用,从而返回恢复的对象。但不知何故,这引发了一堆关于在 hash element 中使用未初始化值的警告。

我尝试重新创建它作为一个小例子。第一段代码是我如何获得示例的 base64 输出。我们将在一分钟内使用它。

use strict;
use warnings;
use MIME::Base64;
use Storable;
use SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType;

my $object = SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType->new;
$object->set_value('foo');
print encode_base64(Storable::freeze($object));

所以我们得到了三行base64。让我们尝试恢复它们:

use strict;
use warnings;
use MIME::Base64;
use Storable;
use Test::Simple tests => 1;

local $/ = undef;
my $object = Storable::thaw(decode_base64(<DATA>));
ok( $object->get_value, 'foo' );

__DATA__
BAgIMTIzNDU2NzgECAgIE0ADAQAAAAQDAQAAAAoDZm9vBQAAAHZhbHVlMAAAAFNPQVA6OldTREw6
OlhTRDo6VHlwZWxpYjo6QnVpbHRpbjo6YW55U2ltcGxlVHlwZYAwU09BUDo6V1NETDo6WFNEOjpU
eXBlbGliOjpCdWlsdGluOjphbnlTaW1wbGVUeXBlEAQICDEyMzQ1Njc4BAgICAUBAAAAAQ==

整洁的。有用!

~> perl foo.t
1..1
ok 1 - foo

现在让我们添加 Test::MockObject。

use strict;
use warnings;
use MIME::Base64;
use Storable;
use Test::Simple tests => 1;
use Test::MockObject; # <------- only line I changed

local $/ = undef;
my $object = Storable::thaw(decode_base64(<DATA>));
ok( $object->get_value, 'foo' );

__DATA__
BAgIMTIzNDU2NzgECAgIE0ADAQAAAAQDAQAAAAoDZm9vBQAAAHZhbHVlMAAAAFNPQVA6OldTREw6
OlhTRDo6VHlwZWxpYjo6QnVpbHRpbjo6YW55U2ltcGxlVHlwZYAwU09BUDo6V1NETDo6WFNEOjpU
eXBlbGliOjpCdWlsdGluOjphbnlTaW1wbGVUeXBlEAQICDEyMzQ1Njc4BAgICAUBAAAAAQ==

好吧,这很奇怪。它可以工作,但会引发错误。

1..1
Use of uninitialized value in hash element at /usr/lib/perl5/site_perl/5.16.2/SOAP/WSDL/XSD/Typelib/Builtin/anySimpleType.pm line 53, <DATA> chunk 1.
ok 1 - foo

所以我查看了 anySimpleType.pm 的第 53 行,它说:

my $OBJECT_CACHE_REF = Class::Std::Fast::OBJECT_CACHE_REF();

sub new {
    my $self = pop @{ $OBJECT_CACHE_REF->{ $_[0] } }; # <-- here
    $self = bless \(my $o = Class::Std::Fast::ID()), $_[0]
        if not defined $self;

唔。$_[0]是未定义的。看起来像是new在没有参数的情况下被调用。

但是加载 Test::MockObject 到底是怎么做到的呢?或者也许这个警告总是弹出,但不知何故以前没有显示?我对其进行了一点调试,结果发现无论我加载了什么,Komodo IDE 调试器中总是显示警告。

但是,如果我也加载了 Test::MockObject,它只会显示在正常的程序输出中。谁能给我解释一下?

4

1 回答 1

0

我仍然不知道为什么会发生这种情况。我的调试使我相信初始化警告总是由这些 Storable 对象引发的。但是,如果 Test::MockObject 不存在,它们将保持沉默。

所以让它闭嘴的解决方法如下:

local $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /uninitialized/};
local $/ = undef;
my $object = Storable::thaw(decode_base64(<DATA>));
ok( $object->get_value, 'foo' );
于 2013-11-21T15:33:00.690 回答