0

因此尝试升级其他人编写的一些旧测试模块以支持更新的 perls。一些测试正在使用 Test::MockObject::Extends,但我发现运行以下代码错误。

#!/usr/bin/env perl

package MyModule;
use strict;
use warnings;
use fields qw(field1 field2);

sub new {
    my $self = shift;
    unless (ref $self) {
        $self = fields::new($self);
    }
    return $self;
}

package main;
use strict;
use warnings;
use Test::MockObject::Extends;
use Data::Dumper;

my $VAR1 = MyModule->new();
print Data::Dumper::Dumper($VAR1);
my $VAR2 = Test::MockObject::Extends->new($VAR1);

错误:

$ perl a
$VAR1 = bless( {}, 'MyModule' );
Modification of a read-only value attempted at /usr/local/share/perl/5.14.2/Test/MockObject/Extends.pm line 31.

我查看了 Test::MockObject 和 perl 5.10 的更改日志,但看不到任何直接看起来会导致此问题的东西。我怀疑它已经坏了一段时间,而 5.10 的一些新东西刚刚照亮了它。

4

2 回答 2

1

I think what's happening here is a result of using fields::new. From the perldoc page:

       perl 5.9.0 and higher:  fields::new() creates and blesses a
      restricted-hash comprised of the fields declared using the "fields"
      pragma into the specified class.

I think Test::MockObject::Extends wants to modify the hash, hence boom.

于 2013-04-09T17:46:16.563 回答
0

@nfg 的答案是正确的,但有一个简单的解决方法:fields在将其传递给Test::Object::Extends.

use Hash::Util qw(unlock_keys);

my $obj = Some::Class->new();
unlock_keys(%$obj);
$obj = Test::MockObject::Extends->new($obj);

如果使用 perl < 5.9,这将失败,所以如果这是一个问题,那么您可以有条件地解锁密钥。

在调用 Test::MockObject::Extends 并模拟任何要拦截的方法后,您可能需要重新锁定键,因为否则访问对象中不应该存在的字段的错误代码将不会被捕获。

于 2017-08-23T01:38:23.463 回答