1Test::MockModule(3pm) User Contributed Perl DocumentationTest::MockModule(3pm)
2
3
4
6 Test::MockModule - Override subroutines in a module for unit testing
7
9 use Module::Name;
10 use Test::MockModule;
11
12 {
13 my $module = Test::MockModule->new('Module::Name');
14 $module->mock('subroutine', sub { ... });
15 Module::Name::subroutine(@args); # mocked
16
17 # Same effect, but this will die() if other_subroutine()
18 # doesn't already exist, which is often desirable.
19 $module->redefine('other_subroutine', sub { ... });
20
21 # This will die() if another_subroutine() is defined.
22 $module->define('another_subroutine', sub { ... });
23 }
24
25 {
26 # you can also chain new/mock/redefine/define
27
28 Test::MockModule->new('Module::Name')
29 ->mock( one_subroutine => sub { ... })
30 ->redefine( other_subroutine => sub { ... } )
31 ->define( a_new_sub => 1234 );
32 }
33
34 Module::Name::subroutine(@args); # original subroutine
35
36 # Working with objects
37 use Foo;
38 use Test::MockModule;
39 {
40 my $mock = Test::MockModule->new('Foo');
41 $mock->mock(foo => sub { print "Foo!\n"; });
42
43 my $foo = Foo->new();
44 $foo->foo(); # prints "Foo!\n"
45 }
46
47 # If you want to prevent noop and mock from working, you can
48 # load Test::MockModule in strict mode.
49
50 use Test::MockModule qw/strict/;
51 my $module = Test::MockModule->new('Module::Name');
52
53 # Redefined the other_subroutine or dies if it's not there.
54 $module->redefine('other_subroutine', sub { ... });
55
56 # Dies since you specified you wanted strict mode.
57 $module->mock('subroutine', sub { ... });
58
59 # Turn strictness off in this lexical scope
60 {
61 use Test::MockModule 'nostrict';
62 # ->mock() works now
63 $module->mock('subroutine', sub { ... });
64 }
65
66 # Back in the strict scope, so mock() dies here
67 $module->mock('subroutine', sub { ... });
68
70 "Test::MockModule" lets you temporarily redefine subroutines in other
71 packages for the purposes of unit testing.
72
73 A "Test::MockModule" object is set up to mock subroutines for a given
74 module. The object remembers the original subroutine so it can be
75 easily restored. This happens automatically when all MockModule objects
76 for the given module go out of scope, or when you unmock() the
77 subroutine.
78
80 One of the weaknesses of testing using mocks is that the implementation
81 of the interface that you are mocking might change, while your mocks
82 get left alone. You are not now mocking what you thought you were, and
83 your mocks might now be hiding bugs that will only be spotted in
84 production. To help prevent this you can load Test::MockModule in
85 'strict' mode:
86
87 use Test::MockModule qw(strict);
88
89 This will disable use of the mock() method, making it a fatal runtime
90 error. You should instead define mocks using redefine(), which will
91 only mock things that already exist and die if you try to redefine
92 something that doesn't exist.
93
94 Strictness is lexically scoped, so you can do this in one file:
95
96 use Test::MockModule qw(strict);
97
98 ...->redefine(...);
99
100 and this in another:
101
102 use Test::MockModule; # the default is nostrict
103
104 ...->mock(...);
105
106 You can even mix n match at different places in a single file thus:
107
108 use Test::MockModule qw(strict);
109 # here mock() dies
110
111 {
112 use Test::MockModule qw(nostrict);
113 # here mock() works
114 }
115
116 # here mock() goes back to dieing
117
118 use Test::MockModule qw(nostrict);
119 # and from here on mock() works again
120
121 NB that strictness must be defined at compile-time, and set using
122 "use". If you think you're going to try and be clever by calling
123 Test::MockModule's import() method at runtime then what happens in
124 undefined, with results differing from one version of perl to another.
125 What larks!
126
128 new($package[, %options])
129 Returns an object that will mock subroutines in the specified
130 $package.
131
132 If there is no $VERSION defined in $package, the module will be
133 automatically loaded. You can override this behaviour by setting
134 the "no_auto" option:
135
136 my $mock = Test::MockModule->new('Module::Name', no_auto => 1);
137
138 get_package()
139 Returns the target package name for the mocked subroutines
140
141 is_mocked($subroutine)
142 Returns a boolean value indicating whether or not the subroutine is
143 currently mocked
144
145 mock($subroutine => \&coderef)
146 Temporarily replaces one or more subroutines in the mocked module.
147 A subroutine can be mocked with a code reference or a scalar. A
148 scalar will be recast as a subroutine that returns the scalar.
149
150 Returns the current "Test::MockModule" object, so you can chain new
151 with mock.
152
153 my $mock = Test::MockModule->new->(...)->mock(...);
154
155 The following statements are equivalent:
156
157 $module->mock(purge => 'purged');
158 $module->mock(purge => sub { return 'purged'});
159
160 When dealing with references, things behave slightly differently.
161 The following statements are NOT equivalent:
162
163 # Returns the same arrayref each time, with the localtime() at time of mocking
164 $module->mock(updated => [localtime()]);
165 # Returns a new arrayref each time, with up-to-date localtime() value
166 $module->mock(updated => sub { return [localtime()]});
167
168 The following statements are in fact equivalent:
169
170 my $array_ref = [localtime()]
171 $module->mock(updated => $array_ref)
172 $module->mock(updated => sub { return $array_ref });
173
174 However, "undef" is a special case. If you mock a subroutine with
175 "undef" it will install an empty subroutine
176
177 $module->mock(purge => undef);
178 $module->mock(purge => sub { });
179
180 rather than a subroutine that returns "undef":
181
182 $module->mock(purge => sub { undef });
183
184 You can call mock() for the same subroutine many times, but when
185 you call unmock(), the original subroutine is restored (not the
186 last mocked instance).
187
188 MOCKING + EXPORT
189
190 If you are trying to mock a subroutine exported from another
191 module, this may not behave as you initially would expect, since
192 Test::MockModule is only mocking at the target module, not anything
193 importing that module. If you mock the local package, or use a
194 fully qualified function name, you will get the behavior you
195 desire:
196
197 use Test::MockModule;
198 use Test::More;
199 use POSIX qw/strftime/;
200
201 my $posix = Test::MockModule->new("POSIX");
202
203 $posix->mock("strftime", "Yesterday");
204 is strftime("%D", localtime(time)), "Yesterday", "`strftime` was mocked successfully"; # Fails
205 is POSIX::strftime("%D", localtime(time)), "Yesterday", "`strftime` was mocked successfully"; # Succeeds
206
207 my $main = Test::MockModule->new("main", no_auto => 1);
208 $main->mock("strftime", "today");
209 is strftime("%D", localtime(time)), "today", "`strftime` was mocked successfully"; # Succeeds
210
211 If you are trying to mock a subroutine that was exported into a
212 module that you're trying to test, rather than mocking the
213 subroutine in its originating module, you can instead mock it in
214 the module you are testing:
215
216 package MyModule;
217 use POSIX qw/strftime/;
218
219 sub minus_twentyfour
220 {
221 return strftime("%a, %b %d, %Y", localtime(time - 86400));
222 }
223
224 package main;
225 use Test::More;
226 use Test::MockModule;
227
228 my $posix = Test::MockModule->new("POSIX");
229 $posix->mock("strftime", "Yesterday");
230
231 is MyModule::minus_twentyfour(), "Yesterday", "`minus-twentyfour` got mocked"; # fails
232
233 my $mymodule = Test::MockModule->new("MyModule", no_auto => 1);
234 $mymodule->mock("strftime", "Yesterday");
235 is MyModule::minus_twentyfour(), "Yesterday", "`minus-twentyfour` got mocked"; # succeeds
236
237 redefine($subroutine)
238 The same behavior as mock(), but this will preemptively check to be
239 sure that all passed subroutines actually exist. This is useful to
240 ensure that if a mocked module's interface changes the test doesn't
241 just keep on testing a code path that no longer behaves
242 consistently with the mocked behavior.
243
244 Note that redefine is also now checking if one of the parent
245 provides the sub and will not die if it's available in the chain.
246
247 Returns the current "Test::MockModule" object, so you can chain new
248 with redefine.
249
250 my $mock = Test::MockModule->new->(...)->redefine(...);
251
252 define($subroutine)
253 The reverse of redefine, this will fail if the passed subroutine
254 exists. While this use case is rare, there are times where the
255 perl code you are testing is inspecting a package and adding a
256 missing subroutine is actually what you want to do.
257
258 By using define, you're asserting that the subroutine you want to
259 be mocked should not exist in advance.
260
261 Note: define does not check for inheritance like redefine.
262
263 Returns the current "Test::MockModule" object, so you can chain new
264 with define.
265
266 my $mock = Test::MockModule->new->(...)->define(...);
267
268 original($subroutine)
269 Returns the original (unmocked) subroutine
270
271 Here is a sample how to wrap a function with custom arguments using
272 the original subroutine. This is useful when you cannot (do not)
273 want to alter the original code to abstract one hardcoded argument
274 pass to a function.
275
276 package MyModule;
277
278 sub sample {
279 return get_path_for("/a/b/c/d");
280 }
281
282 sub get_path_for {
283 ... # anything goes there...
284 }
285
286 package main;
287 use Test::MockModule;
288
289 my $mock = Test::MockModule->new("MyModule");
290 # replace all calls to get_path_for using a different argument
291 $mock->redefine("get_path_for", sub {
292 return $mock->original("get_path_for")->("/my/custom/path");
293 });
294
295 # or
296
297 $mock->redefine("get_path_for", sub {
298 my $path = shift;
299 if ( $path && $path eq "/a/b/c/d" ) {
300 # only alter calls with path set to "/a/b/c/d"
301 return $mock->original("get_path_for")->("/my/custom/path");
302 } else { # preserve the original arguments
303 return $mock->original("get_path_for")->($path, @_);
304 }
305 });
306
307 unmock($subroutine [, ...])
308 Restores the original $subroutine. You can specify a list of
309 subroutines to unmock() in one go.
310
311 unmock_all()
312 Restores all the subroutines in the package that were mocked. This
313 is automatically called when all "Test::MockObject" objects for the
314 given package go out of scope.
315
316 noop($subroutine [, ...])
317 Given a list of subroutine names, mocks each of them with a no-op
318 subroutine. Handy for mocking methods you want to ignore!
319
320 # Neuter a list of methods in one go
321 $module->noop('purge', 'updated');
322
323 TRACE
324 A stub for Log::Trace
325
326 DUMP
327 A stub for Log::Trace
328
330 Test::MockObject::Extends
331
332 Sub::Override
333
335 Current Maintainer: Geoff Franks <gfranks@cpan.org>
336
337 Original Author: Simon Flack <simonflk _AT_ cpan.org>
338
339 Lexical scoping of strictness: David Cantrell <david@cantrell.org.uk>
340
342 Copyright 2004 Simon Flack <simonflk _AT_ cpan.org>. All rights
343 reserved
344
345 You may distribute under the terms of either the GNU General Public
346 License or the Artistic License, as specified in the Perl README file.
347
348
349
350perl v5.38.0 2023-07-21 Test::MockModule(3pm)