1Sub::Override(3) User Contributed Perl Documentation Sub::Override(3)
2
3
4
6 Sub::Override - Perl extension for easily overriding subroutines
7
9 0.09
10
12 use Sub::Override;
13
14 sub foo { 'original sub' };
15 print foo(); # prints 'original sub'
16
17 my $override = Sub::Override->new( foo => sub { 'overridden sub' } );
18 print foo(); # prints 'overridden sub'
19 $override->restore;
20 print foo(); # prints 'original sub'
21
23 The Problem
24 Sometimes subroutines need to be overridden. In fact, your author does
25 this constantly for tests. Particularly when testing, using a Mock
26 Object can be overkill when all you want to do is override one tiny,
27 little function.
28
29 Overriding a subroutine is often done with syntax similar to the
30 following.
31
32 {
33 local *Some::sub = sub {'some behavior'};
34 # do something
35 }
36 # original subroutine behavior restored
37
38 This has a few problems.
39
40 {
41 local *Get::some_feild = { 'some behavior' };
42 # do something
43 }
44
45 In the above example, not only have we probably misspelled the
46 subroutine name, but even if their had been a subroutine with that
47 name, we haven't overridden it. These two bugs can be subtle to
48 detect.
49
50 Further, if we're attempting to localize the effect by placing this
51 code in a block, the entire construct is cumbersome.
52
53 Hook::LexWrap also allows us to override sub behavior, but I can never
54 remember the exact syntax.
55
56 An easier way to replace subroutines
57 Instead, "Sub::Override" allows the programmer to simply name the sub
58 to replace and to supply a sub to replace it with.
59
60 my $override = Sub::Override->new('Some::sub', sub {'new data'});
61
62 # which is equivalent to:
63 my $override = Sub::Override->new;
64 $override->replace('Some::sub', sub { 'new data' });
65
66 You can replace multiple subroutines, if needed:
67
68 $override->replace('Some::sub1', sub { 'new data1' });
69 $override->replace('Some::sub2', sub { 'new data2' });
70 $override->replace('Some::sub3', sub { 'new data3' });
71
72 If replacing the subroutine succeeds, the object is returned. This
73 allows the programmer to chain the calls, if this style of programming
74 is preferred:
75
76 $override->replace('Some::sub1', sub { 'new data1' })
77 ->replace('Some::sub2', sub { 'new data2' })
78 ->replace('Some::sub3', sub { 'new data3' });
79
80 If the subroutine has a prototype, the new subroutine should be
81 declared with same prototype as original one:
82
83 $override->replace('Some::sub_with_proto', sub ($$) { ($_[0], $_ [1]) });
84
85 A subroutine may be replaced as many times as desired. This is most
86 useful when testing how code behaves with multiple conditions.
87
88 $override->replace('Some::thing', sub { 0 });
89 is($object->foo, 'wibble', 'wibble is returned if Some::thing is false');
90
91 $override->replace('Some::thing', sub { 1 });
92 is($object->foo, 'puppies', 'puppies are returned if Some::thing is true');
93
94 Restoring subroutines
95 If the object falls out of scope, the original subs are restored.
96 However, if you need to restore a subroutine early, just use the
97 restore method:
98
99 my $override = Sub::Override->new('Some::sub', sub {'new data'});
100 # do stuff
101 $override->restore;
102
103 Which is somewhat equivalent to:
104
105 {
106 my $override = Sub::Override->new('Some::sub', sub {'new data'});
107 # do stuff
108 }
109
110 If you have override more than one subroutine with an override object,
111 you will have to explicitly name the subroutine you wish to restore:
112
113 $override->restore('This::sub');
114
115 Note "restore()" will always restore the original behavior of the
116 subroutine no matter how many times you have overridden it.
117
118 Which package is the subroutine in?
119 Ordinarily, you want to fully qualify the subroutine by including the
120 package name. However, failure to fully qualify the subroutine name
121 will assume the current package.
122
123 package Foo;
124 use Sub::Override;
125 sub foo { 23 };
126 my $override = Sub::Override->new( foo => sub { 42 } ); # assumes Foo::foo
127 print foo(); # prints 42
128 $override->restore;
129 print foo(); # prints 23
130
132 new
133 my $sub = Sub::Override->new;
134 my $sub = Sub::Override->new($sub_name, $sub_ref);
135
136 Creates a new "Sub::Override" instance. Optionally, you may override a
137 subroutine while creating a new object.
138
139 replace
140 $sub->replace($sub_name, $sub_body);
141
142 Temporarily replaces a subroutine with another subroutine. Returns the
143 instance, so chaining the method is allowed:
144
145 $sub->replace($sub_name, $sub_body)
146 ->replace($another_sub, $another_body);
147
148 This method will "croak" is the subroutine to be replaced does not
149 exist.
150
151 override
152 my $sub = Sub::Override->new;
153 $sub->override($sub_name, $sub_body);
154
155 "override" is an alternate name for "replace". They are the same
156 method.
157
158 restore
159 $sub->restore($sub_name);
160
161 Restores the previous behavior of the subroutine. This will happen
162 automatically if the "Sub::Override" object falls out of scope.
163
165 None by default.
166
168 Probably. Tell me about 'em.
169
171 · Hook::LexWrap -- can also override subs, but with different
172 capabilities
173
174 · Test::MockObject -- use this if you need to alter an entire class
175
177 Curtis "Ovid" Poe, "<ovid [at] cpan [dot] org>"
178
179 Reverse the name to email me.
180
182 Copyright (C) 2004-2005 by Curtis "Ovid" Poe
183
184 This library is free software; you can redistribute it and/or modify it
185 under the same terms as Perl itself, either Perl version 5.8.2 or, at
186 your option, any later version of Perl 5 you may have available.
187
188
189
190perl v5.30.0 2019-07-26 Sub::Override(3)