type constraints now stringify to their name (phaylon)
[gitmo/Moose.git] / t / 046_roles_and_required_method_edge_cases.t
CommitLineData
0558683c 1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
825a80de 6use Test::More tests => 18;
0558683c 7use Test::Exception;
8
9BEGIN {
10 use_ok('Moose');
11 use_ok('Moose::Role');
12}
13
14=pod
15
16Role which requires a method implemented
17in another role as an override (it does
18not remove the requirement)
19
20=cut
21
22{
23 package Role::RequireFoo;
24 use strict;
25 use warnings;
26 use Moose::Role;
27
28 requires 'foo';
29
30 package Role::ProvideFoo;
31 use strict;
32 use warnings;
33 use Moose::Role;
34
35 ::lives_ok {
36 with 'Role::RequireFoo';
37 } '... the required "foo" method will not exist yet (but we will live)';
38
39 override 'foo' => sub { 'Role::ProvideFoo::foo' };
40}
41
42is_deeply(
43 [ Role::ProvideFoo->meta->get_required_method_list ],
44 [ 'foo' ],
45 '... foo method is still required for Role::ProvideFoo');
46
47=pod
48
49Role which requires a method implemented
50in the consuming class as an override.
51It will fail since method modifiers are
52second class citizens.
53
54=cut
55
56{
57 package Class::ProvideFoo::Base;
58 use Moose;
59
60 sub foo { 'Class::ProvideFoo::Base::foo' }
61
62 package Class::ProvideFoo::Override1;
63 use Moose;
64
65 extends 'Class::ProvideFoo::Base';
66
67 ::dies_ok {
68 with 'Role::RequireFoo';
69 } '... the required "foo" method will not exist yet (and we will die)';
70
71 override 'foo' => sub { 'Class::ProvideFoo::foo' };
72
73 package Class::ProvideFoo::Override2;
74 use Moose;
75
76 extends 'Class::ProvideFoo::Base';
77
78 override 'foo' => sub { 'Class::ProvideFoo::foo' };
79
80 ::dies_ok {
81 with 'Role::RequireFoo';
82 } '... the required "foo" method exists, but it is an override (and we will die)';
83
84}
85
86=pod
87
88Now same thing, but with a before
89method modifier.
90
91=cut
92
93{
94 package Class::ProvideFoo::Before1;
95 use Moose;
96
97 extends 'Class::ProvideFoo::Base';
98
99 ::dies_ok {
100 with 'Role::RequireFoo';
101 } '... the required "foo" method will not exist yet (and we will die)';
102
103 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
104
105 package Class::ProvideFoo::Before2;
106 use Moose;
107
108 extends 'Class::ProvideFoo::Base';
109
110 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
111
112 ::dies_ok {
113 with 'Role::RequireFoo';
114 } '... the required "foo" method exists, but it is a before (and we will die)';
115
116 package Class::ProvideFoo::Before3;
117 use Moose;
118
119 extends 'Class::ProvideFoo::Base';
120
121 ::lives_ok {
122 with 'Role::RequireFoo';
123 } '... the required "foo" method will not exist yet (and we will die)';
124
125 sub foo { 'Class::ProvideFoo::foo' }
126 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
127
128 package Class::ProvideFoo::Before4;
129 use Moose;
130
131 extends 'Class::ProvideFoo::Base';
132
133 sub foo { 'Class::ProvideFoo::foo' }
134 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
135
136 ::isa_ok(__PACKAGE__->meta->get_method('foo'), 'Class::MOP::Method::Wrapped');
137 ::is(__PACKAGE__->meta->get_method('foo')->get_original_method->package_name, __PACKAGE__,
138 '... but the original method is from our package');
139
140 ::lives_ok {
141 with 'Role::RequireFoo';
142 } '... the required "foo" method exists in the symbol table (and we will live)';
143
144 package Class::ProvideFoo::Before5;
145 use Moose;
146
147 extends 'Class::ProvideFoo::Base';
148
149 before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
150
151 ::isa_ok(__PACKAGE__->meta->get_method('foo'), 'Class::MOP::Method::Wrapped');
152 ::isnt(__PACKAGE__->meta->get_method('foo')->get_original_method->package_name, __PACKAGE__,
153 '... but the original method is not from our package');
154
155 ::dies_ok {
156 with 'Role::RequireFoo';
157 } '... the required "foo" method exists, but it is a before wrapping the super (and we will die)';
158}
159
160=pod
161
162Now same thing, but with a method from an attribute
163method modifier.
164
165=cut
166
167{
168
169 package Class::ProvideFoo::Attr1;
170 use Moose;
171
172 extends 'Class::ProvideFoo::Base';
173
174 ::dies_ok {
175 with 'Role::RequireFoo';
176 } '... the required "foo" method will not exist yet (and we will die)';
177
178 has 'foo' => (is => 'ro');
179
180 package Class::ProvideFoo::Attr2;
181 use Moose;
182
183 extends 'Class::ProvideFoo::Base';
184
185 has 'foo' => (is => 'ro');
186
187 ::dies_ok {
188 with 'Role::RequireFoo';
189 } '... the required "foo" method exists, but it is a before (and we will die)';
190}
825a80de 191
192# ...
193# a method required in a role, but then
194# implemented in the superclass (as an
195# attribute accessor too)
196
197{
198 package Foo::Class::Base;
199 use Moose;
200
201 has 'bar' => (
202 isa => 'Int',
203 is => 'rw',
204 default => sub { 1 }
205 );
206}
207{
208 package Foo::Role;
209 use Moose::Role;
210
211 requires 'bar';
0558683c 212
825a80de 213 has 'foo' => (
214 isa => 'Int',
215 is => 'rw',
216 lazy => 1,
217 default => sub { (shift)->bar + 1 }
218 );
219}
220{
221 package Foo::Class::Child;
222 use Moose;
223 extends 'Foo::Class::Base';
224
225 ::dies_ok {
226 with 'Foo::Role';
227 } '... our role combined successfully';
228}
229
230
231