BEGIN { package Class; use strict; use warnings; use Moose; has val => ( is => 'rw', isa => 'Num', required => 1, ); use Moose::Util::TypeConstraints; coerce __PACKAGE__ => from 'Num' => via { __PACKAGE__->new(val => $_) }; } BEGIN { package Container; use strict; use warnings; use Moose; has always => ( is => 'rw', isa => 'Class', coerce => 1, default => sub { Class->new(val => 0) }, ); has union => ( is => 'rw', isa => 'Undef|Class', coerce => 1, default => undef, ); } use strict; use warnings; use Test::More tests => 30; use Scalar::Util qw( blessed ); sub ta { $_[0] && blessed($_[0]->always) && blessed($_[0]->always) eq 'Class' } sub tu { $_[0] && ( !$_[0]->union || blessed($_[0]->union) && blessed($_[0]->union) eq 'Class' ) } my $always_fail = qr/^Attribute \(always\) does not pass the type constraint/; my $union_fail = qr/^Attribute \(union\) does not pass the type constraint/; my $o = Class->new(val => 123); my $c; $c = eval { Container->new() }; is($@, ''); ok(ta($c)); $c = eval { Container->new(always => $o) }; is($@, ''); ok(ta($c)); $c = eval { Container->new(always => 123) }; is($@, ''); ok(ta($c)); $c = eval { Container->new(always => "abc") }; like($@, $always_fail); ok(!$c); $c = eval { Container->new(union => undef) }; is($@, ''); ok(tu($c)); $c = eval { Container->new(union => $o) }; is($@, ''); ok(tu($c)); $c = eval { Container->new(union => 123) }; is($@, ''); ok(tu($c)); $c = eval { Container->new(union => "abc") }; like($@, $union_fail); ok(!$c); $c = Container->new(); eval { $c->always($o) }; is($@, ''); ok(tu($c)); eval { $c->always(123) }; is($@, ''); ok(tu($c)); eval { $c->always("abc") }; like($@, $always_fail); ok(tu($c)); eval { $c->union(undef) }; is($@, ''); ok(tu($c)); eval { $c->union($o) }; is($@, ''); ok(tu($c)); eval { $c->union(123) }; is($@, ''); ok(tu($c)); eval { $c->union("abc") }; like($@, $union_fail); ok(tu($c));