1Test2::Mock(3) User Contributed Perl Documentation Test2::Mock(3)
2
3
4
6 Test2::Mock - Module for managing mocked classes and instances.
7
9 This module lets you add and override methods for any package
10 temporarily. When the instance is destroyed it will restore the package
11 to its original state.
12
14 use Test2::Mock;
15 use MyClass;
16
17 my $mock = Test2::Mock->new(
18 class => 'MyClass',
19 override => [
20 name => sub { 'fred' },
21 ...
22 ],
23 add => [
24 is_mocked => sub { 1 }
25 ...
26 ],
27 ...
28 );
29
30 # Unmock the 'name' sub
31 $mock->restore('name');
32
33 ...
34
35 $mock = undef; # Will remove all the mocking
36
39 $mock = Test2::Mock->new(class => $CLASS, ...)
40 This will create a new instance of Test2::Mock that manages mocking
41 for the specified $CLASS.
42
43 Any "Test2::Mock" method can be used as a constructor argument,
44 each should be followed by an arrayref of arguments to be used
45 within the method. For instance the "add()" method:
46
47 my $mock = Test2::Mock->new(
48 class => 'AClass',
49 add => [foo => sub { 'foo' }],
50 );
51
52 is identical to this:
53
54 my $mock = Test2::Mock->new(
55 class => 'AClass',
56 );
57 $mock->add(foo => sub { 'foo' });
58
59 $mock->add('symbol' => ..., 'symbol2' => ...)
60 $mock->override('symbol1' => ..., 'symbol2' => ...)
61 $mock->set('symbol1' => ..., 'symbol2' => ...)
62 "add()" and "override()" are the primary ways to add/modify methods
63 for a class. Both accept the exact same type of arguments. The
64 difference is that "override" will fail unless the symbol you are
65 overriding already exists, "add" on the other hand will fail if the
66 symbol does already exist.
67
68 "set()" was more recently added for cases where you may not know if
69 the sub already exists. These cases are rare, and set should be
70 avoided (think of it like 'no strict'). However there are valid use
71 cases, so it was added.
72
73 Note: Think of override as a push operation. If you call override
74 on the same symbol multiple times it will track that. You can use
75 "restore()" as a pop operation to go back to the previous mock.
76 "reset" can be used to remove all the mocking for a symbol.
77
78 Arguments must be a symbol name, with optional sigil, followed by a
79 new specification of the symbol. If no sigil is specified then '&'
80 (sub) is assumed. A simple example of overriding a sub:
81
82 $mock->override(foo => sub { 'overridden foo' });
83 my $val = $class->foo; # Runs our override
84 # $val is now set to 'overridden foo'
85
86 You can also simply provide a value and it will be wrapped in a sub
87 for you:
88
89 $mock->override( foo => 'foo' );
90
91 The example above will generate a sub that always returns the
92 string 'foo'.
93
94 There are three *special* values that can be used to generate
95 accessors:
96
97 $mock->add(
98 name => 'rw', # Generates a read/write accessor
99 age => 'ro', # Generates a read only accessor
100 size => 'wo', # Generates a write only accessor
101 );
102
103 If you want to have a sub that actually returns one of the three
104 special strings, or that returns a coderef, you can use a hashref
105 as the spec:
106
107 my $ref = sub { 'my sub' };
108 $mock->add(
109 rw_string => { val => 'rw' },
110 ro_string => { val => 'ro' },
111 wo_string => { val => 'wo' },
112 coderef => { val => $ref }, # the coderef method returns $ref each time
113 );
114
115 You can also override/add other symbol types, such as hash:
116
117 package Foo;
118 ...
119
120 $mock->add('%foo' => {a => 1});
121
122 print $Foo::foo{a}; # prints '1'
123
124 You can also tell mock to deduce the symbol type for the
125 add/override from the reference, rules are similar to glob
126 assignments:
127
128 $mock->add(
129 -foo => sub { 'foo' }, # Adds the &foo sub to the package
130 -foo => { foo => 1 }, # Adds the %foo hash to the package
131 -foo => [ 'f', 'o', 'o' ], # Adds the @foo array to the package
132 -foo => \"foo", # Adds the $foo scalar to the package
133 );
134
135 $mock->restore($SYMBOL)
136 Restore the symbol to what it was before the last override. If the
137 symbol was recently added this will remove it. If the symbol has
138 been overridden multiple times this will ONLY restore it to the
139 previous state. Think of "override" as a push operation, and
140 "restore" as the pop operation.
141
142 $mock->reset($SYMBOL)
143 Remove all mocking of the symbol and restore the original symbol.
144 If the symbol was initially added then it will be completely
145 removed.
146
147 $mock->orig($SYMBOL)
148 This will return the original symbol, before any mocking. For
149 symbols that were added this will return undef.
150
151 $mock->current($SYMBOL)
152 This will return the current symbol.
153
154 $mock->reset_all
155 Remove all added symbols, and restore all overridden symbols to
156 their originals.
157
158 $mock->add_constructor($NAME => $TYPE)
159 $mock->override_constructor($NAME => $TYPE)
160 This can be used to inject constructors. The first argument should
161 be the name of the constructor. The second argument specifies the
162 constructor type.
163
164 The "hash" type is the most common, all arguments are used to
165 create a new hash that is blessed.
166
167 hash => sub {
168 my ($class, %params) = @_;
169 return bless \%params, $class;
170 };
171
172 The "array" type is similar to the hash type, but accepts a list
173 instead of key/value pairs:
174
175 array => sub {
176 my ($class, @params) = @_;
177 return bless \@params, $class;
178 };
179
180 The "ref" type takes a reference and blesses it. This will modify
181 your original input argument.
182
183 ref => sub {
184 my ($class, $params) = @_;
185 return bless $params, $class;
186 };
187
188 The "ref_copy" type will copy your reference and bless the copy:
189
190 ref_copy => sub {
191 my ($class, $params) = @_;
192 my $type = reftype($params);
193
194 return bless {%$params}, $class
195 if $type eq 'HASH';
196
197 return bless [@$params], $class
198 if $type eq 'ARRAY';
199
200 croak "Not sure how to construct an '$class' from '$params'";
201 };
202
203 $mock->before($NAME, sub { ... })
204 This will replace the original sub $NAME with a new sub that calls
205 your custom code just before calling the original method. The
206 return from your custom sub is ignored. Your sub and the original
207 both get the unmodified arguments.
208
209 $mock->after($NAME, sub { ... })
210 This is similar to before, except your callback runs after the
211 original code. The return from your callback is ignored.
212
213 $mock->around($NAME, sub { ... })
214 This gives you the chance to wrap the original sub:
215
216 $mock->around(foo => sub {
217 my $orig = shift;
218 my $self = shift;
219 my (@args) = @_;
220
221 ...
222 $orig->(@args);
223 ...
224
225 return ...;
226 });
227
228 The original sub is passed in as the first argument, even before
229 $self. You are responsible for making sure your wrapper sub returns
230 the correct thing.
231
232 $mock->autoload
233 This will inject an "AUTOLOAD" sub into the class. This autoload
234 will automatically generate read-write accessors for any sub called
235 that does not already exist.
236
237 $mock->block_load
238 This will prevent the real class from loading until the mock is
239 destroyed. This will fail if the class is already loaded. This will
240 let you mock a class completely without loading the original
241 module.
242
243 $pm_file = $mock->file
244 This returns the relative path to the file for the module. This
245 corresponds to the %INC entry.
246
247 $bool = $mock->purge_on_destroy($bool)
248 When true, this will cause the package stash to be completely
249 obliterated when the mock object falls out of scope or is otherwise
250 destroyed. You do not normally want this.
251
252 $stash = $mock->stash
253 This returns the stash for the class being mocked. This is the
254 equivalent of:
255
256 my $stash = \%{"${class}\::"};
257
258 This saves you from needing to turn off strict.
259
260 $class = $mock->class
261 The class being mocked by this instance.
262
263 $p = $mock->parent
264 If you mock a class twice the first instance is the parent, the
265 second is the child. This prevents the parent from being destroyed
266 before the child, which would lead to a very unpleasant situation.
267
268 $c = $mock->child
269 Returns the child mock, if any.
270
272 The source code repository for Test2-Suite can be found at
273 https://github.com/Test-More/Test2-Suite/.
274
276 Chad Granum <exodist@cpan.org>
277
279 Chad Granum <exodist@cpan.org>
280
282 Copyright 2018 Chad Granum <exodist@cpan.org>.
283
284 This program is free software; you can redistribute it and/or modify it
285 under the same terms as Perl itself.
286
287 See http://dev.perl.org/licenses/
288
289
290
291perl v5.28.1 2018-12-04 Test2::Mock(3)