是否有一种简单的方法来测试Moose属性是否为只读?

时间:2010-04-01 18:41:21

标签: perl testing tdd attributes moose

我目前使用块eval来测试我是否将属性设置为只读。有更简单的方法吗?

工作代码示例:

#Test that sample_for is ready only
eval { $snp_obj->sample_for('t/sample_manifest2.txt');};
like($@, qr/read-only/xms, "'sample_for' is read-only");



更新

感谢Friedo,Ether和Robert P的回答以及Ether,Robert P和jrockway的评论。

我喜欢以太的答案如何通过用$is_read_only否定!来确保$is_read_only只是一个真值或假值(即从来不是一个coderef)。 Double negation也提供了这一点。因此,您可以在is()函数中使用get_attribute,而不会打印出coderef。

请参阅下面的Robert P的答案,以获得最完整的答案。每个人都非常乐于助人,并建立在彼此的答案和评论之上。总的来说,我认为他对我的帮助最大,因此他现在已成为公认的答案。再次感谢Ether,Robert P,friedo和jrockway。



如果你可能想知道,正如我最初所做的那样,这里有关于find_attribute_by_name$metaclass->get_attribute($attribute_name) This will return a Class::MOP::Attribute for the specified $attribute_name. If the class does not have the specified attribute, it returns undef. NOTE that get_attribute does not search superclasses, for that you need to use find_attribute_by_name. from Class::MOP::Class)之间差异的文档:

{{1}}

3 个答案:

答案 0 :(得分:5)

Class::MOP::Attribute中所述:

my $attr = $this->meta->find_attribute_by_name($attr_name);
my $is_read_only = ! $attr->get_write_method();

$attr->get_write_method()将获取编写器方法(您创建的方法或生成的方法),如果没有,则为undef。

答案 1 :(得分:5)

从技术上讲,属性不需要具有读取或写入方法。 大多数时间,但并非总是如此。下面是一个例子(从jrockway's comment中慷慨地被盗):

has foo => ( 
    isa => 'ArrayRef', 
    traits => ['Array'], 
    handles => { add_foo => 'push', get_foo => 'pop' }
)

此属性将存在,​​但没有标准的读者和作者。

因此,要在每种情况下测试属性已定义为is => 'RO',您需要同时检查write和read方法。您可以使用此子例程执行此操作:

# returns the read method if it exists, or undef otherwise.
sub attribute_is_read_only {
    my ($obj, $attribute_name) = @_;
    my $attribute = $obj->meta->get_attribute($attribute_name);

    return unless defined $attribute;
    return (! $attribute->get_write_method() && $attribute->get_read_method());
}

或者,你可以在最后return之前添加一个双重否定来增加返回值:

return !! (! $attribute->get_write_method() && $attribute->get_read_method());

答案 2 :(得分:3)

你应该能够从对象的元类中获取它:

unless ( $snp_obj->meta->get_attribute( 'sample_for' )->get_write_method ) { 
    # no write method, so it's read-only
}

有关详情,请参阅Class::MOP::Attribute