summaryrefslogtreecommitdiff
path: root/t/exceptions/attribute.t
diff options
context:
space:
mode:
Diffstat (limited to 't/exceptions/attribute.t')
-rw-r--r--t/exceptions/attribute.t1194
1 files changed, 1194 insertions, 0 deletions
diff --git a/t/exceptions/attribute.t b/t/exceptions/attribute.t
new file mode 100644
index 0000000..600f51f
--- /dev/null
+++ b/t/exceptions/attribute.t
@@ -0,0 +1,1194 @@
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Fatal;
+
+# tests for AccessorMustReadWrite
+{
+ use Moose;
+
+ my $exception = exception {
+ has 'test' => (
+ is => 'ro',
+ isa => 'Int',
+ accessor => 'bar',
+ )
+ };
+
+ like(
+ $exception,
+ qr!Cannot define an accessor name on a read-only attribute, accessors are read/write!,
+ "Read-only attributes can't have accessor");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::AccessorMustReadWrite",
+ "Read-only attributes can't have accessor");
+
+ is(
+ $exception->attribute_name,
+ 'test',
+ "Read-only attributes can't have accessor");
+}
+
+# tests for AttributeIsRequired
+{
+ {
+ package Foo;
+ use Moose;
+
+ has 'baz' => (
+ is => 'ro',
+ isa => 'Int',
+ required => 1,
+ );
+ }
+
+ my $exception = exception {
+ Foo->new;
+ };
+
+ like(
+ $exception,
+ qr/\QAttribute (baz) is required/,
+ "... must supply all the required attribute");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::AttributeIsRequired",
+ "... must supply all the required attribute");
+
+ is(
+ $exception->attribute_name,
+ 'baz',
+ "... must supply all the required attribute");
+
+ isa_ok(
+ $exception->class_name,
+ 'Foo',
+ "... must supply all the required attribute");
+}
+
+# tests for invalid value for is
+{
+ my $exception = exception {
+ use Moose;
+ has 'foo' => (
+ is => 'bar',
+ );
+ };
+
+ like(
+ $exception,
+ qr/^\QI do not understand this option (is => bar) on attribute (foo)/,
+ "invalid value for is");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::InvalidValueForIs',
+ "invalid value for is");
+}
+
+{
+ {
+ package Foo;
+ use Moose;
+ }
+
+ my $exception = exception {
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ isa => 'Foo',
+ does => 'Not::A::Role'
+ );
+ };
+
+ like(
+ $exception,
+ qr/^\QCannot have an isa option and a does option if the isa does not do the does on attribute (bar)/,
+ "isa option should does the role on the given attribute");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::IsaDoesNotDoTheRole',
+ "isa option should does the role on the given attribute");
+}
+
+{
+ {
+ package Foo;
+ use Moose;
+ }
+
+ my $exception = exception {
+ has 'bar' => (
+ is => 'ro',
+ isa => 'Not::A::Class',
+ does => 'Not::A::Role',
+ );
+ };
+
+ like(
+ $exception,
+ qr/^\QCannot have an isa option which cannot ->does() on attribute (bar)/,
+ "isa option which is not a class cannot ->does the role specified in does");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::IsaLacksDoesMethod',
+ "isa option which is not a class cannot ->does the role specified in does");
+}
+
+{
+ my $exception = exception {
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ coerce => 1,
+ );
+ };
+
+ like(
+ $exception,
+ qr/^\QYou cannot have coercion without specifying a type constraint on attribute (bar)/,
+ "cannot coerce if type constraint i.e. isa option is not given");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::CoercionNeedsTypeConstraint',
+ "cannot coerce if type constraint i.e. isa option is not given");
+}
+
+{
+ my $exception = exception {
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ isa => 'Int',
+ weak_ref => 1,
+ coerce => 1,
+ );
+ };
+
+ like(
+ $exception,
+ qr/^\QYou cannot have a weak reference to a coerced value on attribute (bar)/,
+ "cannot coerce if attribute is a weak_ref");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::CannotCoerceAWeakRef',
+ "cannot coerce if attribute is a weak_ref");
+}
+
+{
+ my $exception = exception {
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ isa => 'Int',
+ trigger => "foo",
+ );
+ };
+
+ like(
+ $exception,
+ qr/^\QTrigger must be a CODE ref on attribute (bar)/,
+ "Trigger must be a CODE ref");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::TriggerMustBeACodeRef',
+ "Trigger must be a CODE ref");
+}
+
+{
+ {
+ package Foo;
+ use Moose;
+ has 'baz' => (
+ is => 'ro',
+ isa => 'Int',
+ builder => "_build_baz",
+ );
+ }
+
+ my $exception = exception {
+ Foo->new;
+ };
+
+ like(
+ $exception,
+ qr/^\QFoo does not support builder method '_build_baz' for attribute 'baz'/,
+ "Correct error when a builder method is not present");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::BuilderDoesNotExist',
+ "Correct error when a builder method is not present");
+
+ isa_ok(
+ $exception->instance,
+ 'Foo',
+ "Correct error when a builder method is not present");
+
+ is(
+ $exception->attribute->name,
+ 'baz',
+ "Correct error when a builder method is not present");
+
+ is(
+ $exception->attribute->builder,
+ '_build_baz',
+ "Correct error when a builder method is not present");
+}
+
+# tests for CannotDelegateWithoutIsa
+{
+ my $exception = exception {
+ package Foo;
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ handles => qr/baz/,
+ );
+ };
+
+ like(
+ $exception,
+ qr/\QCannot delegate methods based on a Regexp without a type constraint (isa)/,
+ "isa is required while delegating methods based on a Regexp");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::CannotDelegateWithoutIsa',
+ "isa is required while delegating methods based on a Regexp");
+}
+
+{
+ my $exception = exception {
+ package Foo;
+ use Moose;
+ has bar => (
+ is => 'ro',
+ auto_deref => 1,
+ );
+ };
+
+ like(
+ $exception,
+ qr/\QYou cannot auto-dereference without specifying a type constraint on attribute (bar)/,
+ "You cannot auto-dereference without specifying a type constraint on attribute");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::CannotAutoDerefWithoutIsa',
+ "You cannot auto-dereference without specifying a type constraint on attribute");
+
+ is(
+ $exception->attribute_name,
+ 'bar',
+ "You cannot auto-dereference without specifying a type constraint on attribute");
+}
+
+{
+ my $exception = exception {
+ package Foo;
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ required => 1,
+ init_arg => undef,
+ );
+ };
+
+ like(
+ $exception,
+ qr/\QYou cannot have a required attribute (bar) without a default, builder, or an init_arg/,
+ "No default, builder or init_arg is given");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::RequiredAttributeNeedsADefault',
+ "No default, builder or init_arg is given");
+}
+
+{
+ my $exception = exception {
+ package Foo;
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ lazy => 1,
+ );
+ };
+
+ like(
+ $exception,
+ qr/\QYou cannot have a lazy attribute (bar) without specifying a default value for it/,
+ "No default for a lazy attribute is given");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::LazyAttributeNeedsADefault',
+ "No default for a lazy attribute is given");
+}
+
+{
+ my $exception = exception {
+ package Foo;
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ isa => 'Int',
+ auto_deref => 1,
+ );
+ };
+
+ like(
+ $exception,
+ qr/\QYou cannot auto-dereference anything other than a ArrayRef or HashRef on attribute (bar)/,
+ "auto_deref needs either HashRef or ArrayRef");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::AutoDeRefNeedsArrayRefOrHashRef',
+ "auto_deref needs either HashRef or ArrayRef");
+}
+
+{
+ my $exception = exception {
+ package Foo;
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ lazy_build => 1,
+ default => 1,
+ );
+ };
+
+ like(
+ $exception,
+ qr/\QYou can not use lazy_build and default for the same attribute (bar)/,
+ "An attribute can't use lazy_build & default simultaneously");
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::CannotUseLazyBuildAndDefaultSimultaneously',
+ "An attribute can't use lazy_build & default simultaneously");
+}
+
+{
+ my $exception = exception {
+ package Delegator;
+ use Moose;
+
+ sub full { 1 }
+ sub stub;
+
+ has d1 => (
+ isa => 'X',
+ handles => ['full'],
+ );
+ };
+
+ like(
+ $exception,
+ qr/\QYou cannot overwrite a locally defined method (full) with a delegation/,
+ 'got an error when trying to declare a delegation method that overwrites a local method');
+
+ isa_ok(
+ $exception,
+ 'Moose::Exception::CannotDelegateLocalMethodIsPresent',
+ "got an error when trying to declare a delegation method that overwrites a local method");
+
+ $exception = exception {
+ package Delegator;
+ use Moose;
+
+ has d2 => (
+ isa => 'X',
+ handles => ['stub'],
+ );
+ };
+
+ is(
+ $exception,
+ undef,
+ 'no error when trying to declare a delegation method that overwrites a stub method');
+}
+
+{
+ {
+ package Test;
+ use Moose;
+ has 'foo' => (
+ is => 'rw',
+ clearer => 'clear_foo',
+ predicate => 'foo',
+ accessor => 'bar',
+ );
+ }
+
+ my $exception = exception {
+ package Test2;
+ use Moose;
+ extends 'Test';
+ has '+foo' => (
+ clearer => 'clear_foo1',
+ );
+ };
+
+ like(
+ $exception,
+ qr/\QIllegal inherited options => (clearer)/,
+ "Illegal inherited option is given");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::IllegalInheritedOptions",
+ "Illegal inherited option is given");
+
+ $exception = exception {
+ package Test3;
+ use Moose;
+ extends 'Test';
+ has '+foo' => (
+ clearer => 'clear_foo1',
+ predicate => 'xyz',
+ accessor => 'bar2',
+ );
+ };
+
+ like(
+ $exception,
+ qr/\QIllegal inherited options => (accessor, clearer, predicate)/,
+ "Illegal inherited option is given");
+}
+
+# tests for exception thrown is Moose::Meta::Attribute::set_value
+{
+ my $exception = exception {
+ {
+ package Foo1;
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ required => 1,
+ );
+ }
+
+ my $instance = Foo1->new(bar => "test");
+ my $bar_attr = Foo1->meta->get_attribute('bar');
+ my $bar_writer = $bar_attr->get_write_method_ref;
+ $bar_writer->($instance);
+ };
+
+ like(
+ $exception,
+ qr/\QAttribute (bar) is required/,
+ "... must supply all the required attribute");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::AttributeIsRequired",
+ "... must supply all the required attribute");
+
+ is(
+ $exception->attribute_name,
+ 'bar',
+ "... must supply all the required attribute");
+
+ isa_ok(
+ $exception->class_name,
+ 'Foo1',
+ "... must supply all the required attribute");
+}
+
+{
+ my $exception = exception {
+ {
+ package Foo1;
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ handles => \*STDIN,
+ );
+ }
+ };
+
+ my $handle = \*STDIN;
+
+ like(
+ $exception,
+ qr/\QUnable to canonicalize the 'handles' option with $handle/,
+ "handles doesn't take file handle");
+ #Unable to canonicalize the 'handles' option with GLOB(0x109d0b0)
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::UnableToCanonicalizeHandles",
+ "handles doesn't take file handle");
+
+}
+
+{
+ my $exception = exception {
+ {
+ package Foo1;
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ handles => 'Foo1',
+ );
+ }
+ };
+
+ like(
+ $exception,
+ qr/\QUnable to canonicalize the 'handles' option with Foo1 because its metaclass is not a Moose::Meta::Role/,
+ "'Str' given to handles should be a metaclass of Moose::Meta::Role");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::UnableToCanonicalizeNonRolePackage",
+ "'Str' given to handles should be a metaclass of Moose::Meta::Role");
+}
+
+{
+ my $exception = exception {
+ {
+ package Foo1;
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ isa => 'Not::Loaded',
+ handles => qr/xyz/,
+ );
+ }
+ };
+
+ like(
+ $exception,
+ qr/\QThe bar attribute is trying to delegate to a class which has not been loaded - Not::Loaded/,
+ "You cannot delegate to a class which has not yet loaded");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::DelegationToAClassWhichIsNotLoaded",
+ "You cannot delegate to a class which has not yet loaded");
+
+ is(
+ $exception->attribute->name,
+ 'bar',
+ "You cannot delegate to a class which has not yet loaded"
+ );
+
+ is(
+ $exception->class_name,
+ 'Not::Loaded',
+ "You cannot delegate to a class which has not yet loaded"
+ );
+}
+
+{
+ my $exception = exception {
+ {
+ package Foo1;
+ use Moose;
+ has bar => (
+ is => 'ro',
+ does => 'Role',
+ handles => qr/Role/,
+ );
+ }
+ };
+
+ like(
+ $exception,
+ qr/\QThe bar attribute is trying to delegate to a role which has not been loaded - Role/,
+ "You cannot delegate to a role which has not yet loaded");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::DelegationToARoleWhichIsNotLoaded",
+ "You cannot delegate to a role which has not yet loaded");
+
+ is(
+ $exception->attribute->name,
+ 'bar',
+ "You cannot delegate to a role which has not yet loaded"
+ );
+
+ is(
+ $exception->role_name,
+ 'Role',
+ "You cannot delegate to a role which has not yet loaded"
+ );
+}
+
+
+{
+ my $exception = exception {
+ {
+ package Foo1;
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ isa => 'Int',
+ handles => qr/xyz/,
+ );
+ }
+ };
+
+ like(
+ $exception,
+ qr/\QThe bar attribute is trying to delegate to a type (Int) that is not backed by a class/,
+ "Delegating to a type that is not backed by a class");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::DelegationToATypeWhichIsNotAClass",
+ "Delegating to a type that is not backed by a class");
+
+ is(
+ $exception->attribute->name,
+ 'bar',
+ "Delegating to a type that is not backed by a class");
+
+ is(
+ $exception->attribute->type_constraint->name,
+ 'Int',
+ "Delegating to a type that is not backed by a class");
+
+ $exception = exception {
+ {
+ package Foo1;
+ use Moose;
+ use Moose::Util::TypeConstraints;
+
+ subtype 'PositiveInt',
+ as 'Int',
+ where { $_ > 0 };
+
+ has 'bar' => (
+ is => 'ro',
+ isa => 'PositiveInt',
+ handles => qr/xyz/,
+ );
+ }
+ };
+
+ like(
+ $exception,
+ qr/\QThe bar attribute is trying to delegate to a type (PositiveInt) that is not backed by a class/,
+ "Delegating to a type that is not backed by a class");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::DelegationToATypeWhichIsNotAClass",
+ "Delegating to a type that is not backed by a class");
+
+ is(
+ $exception->attribute->type_constraint->name,
+ 'PositiveInt',
+ "Delegating to a type that is not backed by a class");
+}
+
+{
+ my $exception = exception {
+ {
+ package Foo1;
+ use Moose;
+ has 'bar' => (
+ is => 'ro',
+ does => '',
+ handles => qr/xyz/,
+ );
+ }
+ };
+
+ like(
+ $exception,
+ qr/Cannot find delegate metaclass for attribute bar/,
+ "no does or isa is given");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::CannotFindDelegateMetaclass",
+ "no does or isa is given");
+
+ is(
+ $exception->attribute->name,
+ 'bar',
+ "no does or isa is given");
+}
+
+# tests for type coercions
+{
+ use Moose;
+ use Moose::Util::TypeConstraints;
+ subtype 'HexNum' => as 'Int', where { /[a-f0-9]/i };
+ my $type_object = find_type_constraint 'HexNum';
+
+ my $exception = exception {
+ $type_object->coerce;
+ };
+
+ like(
+ $exception,
+ qr/Cannot coerce without a type coercion/,
+ "You cannot coerce a type unless coercion is supported by that type");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::CoercingWithoutCoercions",
+ "You cannot coerce a type unless coercion is supported by that type");
+
+ is(
+ $exception->type_name,
+ 'HexNum',
+ "You cannot coerce a type unless coercion is supported by that type");
+}
+
+{
+ {
+ package Parent;
+ use Moose;
+
+ has foo => (
+ is => 'rw',
+ isa => 'Num',
+ default => 5.5,
+ );
+ }
+
+ {
+ package Child;
+ use Moose;
+ extends 'Parent';
+
+ has '+foo' => (
+ isa => 'Int',
+ default => 100,
+ );
+ }
+
+ my $foo = Child->new;
+ my $exception = exception {
+ $foo->foo(10.5);
+ };
+
+ like(
+ $exception,
+ qr/\QAttribute (foo) does not pass the type constraint because: Validation failed for 'Int' with value 10.5/,
+ "10.5 is not an Int");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::ValidationFailedForInlineTypeConstraint",
+ "10.5 is not an Int");
+
+ is(
+ $exception->class_name,
+ "Child",
+ "10.5 is not an Int");
+}
+
+{
+ {
+ package Foo2;
+ use Moose;
+
+ has a4 => (
+ traits => ['Array'],
+ is => 'rw',
+ isa => 'ArrayRef',
+ lazy => 1,
+ default => 'invalid',
+ clearer => '_clear_a4',
+ handles => {
+ get_a4 => 'get',
+ push_a4 => 'push',
+ accessor_a4 => 'accessor',
+ },
+ );
+
+ has a5 => (
+ traits => ['Array'],
+ is => 'rw',
+ isa => 'ArrayRef[Int]',
+ lazy => 1,
+ default => sub { [] },
+ clearer => '_clear_a5',
+ handles => {
+ get_a5 => 'get',
+ push_a5 => 'push',
+ accessor_a5 => 'accessor',
+ },
+ );
+ }
+
+ my $foo = Foo2->new;
+
+ my $expect
+ = qr/\QAttribute (a4) does not pass the type constraint because: Validation failed for 'ArrayRef' with value \E.*invalid.*/;
+
+ my $exception = exception { $foo->accessor_a4(0); };
+
+ like(
+ $exception,
+ $expect,
+ 'invalid default is caught when trying to read via accessor');
+ #Attribute (a4) does not pass the type constraint because: Validation failed for 'ArrayRef' with value "invalid"
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::ValidationFailedForInlineTypeConstraint",
+ 'invalid default is caught when trying to read via accessor');
+
+ is(
+ $exception->class_name,
+ "Foo2",
+ 'invalid default is caught when trying to read via accessor');
+
+ $exception = exception { $foo->accessor_a4( 0 => 42 ); };
+
+ like(
+ $exception,
+ $expect,
+ 'invalid default is caught when trying to write via accessor');
+ #Attribute (a4) does not pass the type constraint because: Validation failed for 'ArrayRef' with value "invalid"
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::ValidationFailedForInlineTypeConstraint",
+ 'invalid default is caught when trying to write via accessor');
+
+ is(
+ $exception->class_name,
+ "Foo2",
+ 'invalid default is caught when trying to write via accessor');
+
+ $exception = exception { $foo->push_a4(42); };
+
+ like(
+ $exception,
+ $expect,
+ 'invalid default is caught when trying to push');
+ #Attribute (a4) does not pass the type constraint because: Validation failed for 'ArrayRef' with value "invalid"
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::ValidationFailedForInlineTypeConstraint",
+ 'invalid default is caught when trying to push');
+
+ is(
+ $exception->class_name,
+ "Foo2",
+ 'invalid default is caught when trying to push');
+
+ $exception = exception { $foo->get_a4(42); };
+
+ like(
+ $exception,
+ $expect,
+ 'invalid default is caught when trying to get');
+ #Attribute (a4) does not pass the type constraint because: Validation failed for 'ArrayRef' with value "invalid"
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::ValidationFailedForInlineTypeConstraint",
+ 'invalid default is caught when trying to get');
+
+ is(
+ $exception->class_name,
+ "Foo2",
+ 'invalid default is caught when trying to get');
+}
+
+{
+ my $class = Moose::Meta::Class->create("RedundantClass");
+ my $attr = Moose::Meta::Attribute->new('foo', (auto_deref => 1,
+ isa => 'ArrayRef',
+ is => 'ro'
+ )
+ );
+ my $attr2 = $attr->clone_and_inherit_options( isa => 'Int');
+
+ my $exception = exception {
+ $attr2->get_value($class);
+ };
+
+ like(
+ $exception,
+ qr/Can not auto de-reference the type constraint 'Int'/,
+ "Cannot auto-deref with 'Int'");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::CannotAutoDereferenceTypeConstraint",
+ "Cannot auto-deref with 'Int'");
+
+ is(
+ $exception->attribute->name,
+ "foo",
+ "Cannot auto-deref with 'Int'");
+
+ is(
+ $exception->type_name,
+ "Int",
+ "Cannot auto-deref with 'Int'");
+}
+
+{
+ {
+ my $parameterizable = subtype 'ParameterizableArrayRef', as 'ArrayRef';
+ my $int = find_type_constraint('Int');
+ my $from_parameterizable = $parameterizable->parameterize($int);
+
+ {
+ package Parameterizable;
+ use Moose;
+
+ has from_parameterizable => ( is => 'rw', isa => $from_parameterizable );
+ }
+ }
+
+ my $params = Parameterizable->new();
+ my $exception = exception {
+ $params->from_parameterizable( 'Hello' );
+ };
+
+ like(
+ $exception,
+ qr/\QAttribute (from_parameterizable) does not pass the type constraint because: Validation failed for 'ParameterizableArrayRef[Int]'\E with value "?Hello"?/,
+ "'Hello' is a Str");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::ValidationFailedForInlineTypeConstraint",
+ "'Hello' is a Str");
+
+ is(
+ $exception->class_name,
+ "Parameterizable",
+ "'Hello' is a Str");
+
+ is(
+ $exception->value,
+ "Hello",
+ "'Hello' is a Str");
+
+ is(
+ $exception->attribute_name,
+ "from_parameterizable",
+ "'Hello' is a Str");
+}
+
+{
+ {
+ package Test::LazyBuild::Attribute;
+ use Moose;
+
+ has 'fool' => ( lazy_build => 1, is => 'ro');
+ }
+
+ my $instance = Test::LazyBuild::Attribute->new;
+
+ my $exception = exception {
+ $instance->fool;
+ };
+
+ like(
+ $exception,
+ qr/\QTest::LazyBuild::Attribute does not support builder method '_build_fool' for attribute 'fool' /,
+ "builder method _build_fool doesn't exist");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::BuilderMethodNotSupportedForInlineAttribute",
+ "builder method _build_fool doesn't exist");
+
+ is(
+ $exception->attribute_name,
+ "fool",
+ "builder method _build_fool doesn't exist");
+
+ is(
+ $exception->builder,
+ "_build_fool",
+ "builder method _build_fool doesn't exist");
+
+ is(
+ $exception->class_name,
+ "Test::LazyBuild::Attribute",
+ "builder method _build_fool doesn't exist");
+}
+
+{
+ {
+ package Foo::Required;
+ use Moose;
+
+ has 'foo_required' => (
+ reader => 'get_foo_required',
+ writer => 'set_foo_required',
+ required => 1,
+ );
+ }
+
+ my $foo = Foo::Required->new(foo_required => "required");
+
+ my $exception = exception {
+ $foo->set_foo_required();
+ };
+
+ like(
+ $exception,
+ qr/\QAttribute (foo_required) is required/,
+ "passing no value to set_foo_required");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::AttributeIsRequired",
+ "passing no value to set_foo_required");
+
+ is(
+ $exception->attribute_name,
+ 'foo_required',
+ "passing no value to set_foo_required");
+
+ isa_ok(
+ $exception->class_name,
+ 'Foo::Required',
+ "passing no value to set_foo_required");
+}
+
+{
+ use Moose::Util::TypeConstraints;
+
+ my $exception = exception {
+ {
+ package BadMetaClass;
+ use Moose;
+
+ has 'foo' => (
+ is => 'ro',
+ isa => "Moose::Util::TypeConstraints",
+ handles => qr/hello/
+ );
+ }
+ };
+
+ like(
+ $exception,
+ qr/Unable to recognize the delegate metaclass 'Class::MOP::Package/,
+ "unable to recognize metaclass of Moose::Util::TypeConstraints");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::UnableToRecognizeDelegateMetaclass",
+ "unable to recognize metaclass of Moose::Util::TypeConstraints");
+
+ is(
+ $exception->attribute->name,
+ 'foo',
+ "unable to recognize metaclass of Moose::Util::TypeConstraints");
+
+ is(
+ $exception->delegate_metaclass->name,
+ 'Moose::Util::TypeConstraints',
+ "unable to recognize metaclass of Moose::Util::TypeConstraints");
+}
+
+{
+ my $exception = exception {
+ package Foo::CannotCoerce::WithoutCoercion;
+ use Moose;
+
+ has 'foo' => (
+ is => 'ro',
+ isa => 'Str',
+ coerce => 1
+ )
+ };
+
+ like(
+ $exception,
+ qr/\QYou cannot coerce an attribute (foo) unless its type (Str) has a coercion/,
+ "has throws error with odd number of attribute options");
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::CannotCoerceAttributeWhichHasNoCoercion",
+ "has throws error with odd number of attribute options");
+
+ is(
+ $exception->attribute_name,
+ 'foo',
+ "has throws error with odd number of attribute options");
+
+ is(
+ $exception->type_name,
+ 'Str',
+ "has throws error with odd number of attribute options");
+}
+
+{
+ my $exception = exception {
+ {
+ package Foo1;
+ use Moose;
+ has 'bar' => (
+ is =>
+ );
+ }
+ };
+
+ like(
+ $exception,
+ qr/\QYou must pass an even number of attribute options/,
+ 'has throws exception with odd number of attribute options');
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::MustPassEvenNumberOfAttributeOptions",
+ 'has throws exception with odd number of attribute options');
+
+ is(
+ $exception->attribute_name,
+ 'bar',
+ 'has throws exception with odd number of attribute options');
+}
+
+{
+ my $exception = exception {
+ {
+ package Foo1;
+ use Moose;
+ has bar => (
+ is => 'ro',
+ required => 1,
+ isa => 'Int',
+ );
+ }
+
+ Foo1->new(bar => "test");
+ };
+
+ like(
+ $exception,
+ qr/^Attribute \(bar\) does not pass the type constraint because: Validation failed for 'Int' with value "?test"?/,
+ "bar is an 'Int' and 'Str' is given");
+ #Attribute (bar) does not pass the type constraint because: Validation failed for 'Int' with value "test"
+
+ isa_ok(
+ $exception,
+ "Moose::Exception::ValidationFailedForTypeConstraint",
+ "bar is an 'Int' and 'Str' is given");
+}
+
+done_testing;