1Test::MockModule(3pm) User Contributed Perl DocumentationTest::MockModule(3pm)
2
3
4

NAME

6       Test::MockModule - Override subroutines in a module for unit testing
7

SYNOPSIS

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

DESCRIPTION

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

STRICT MODE

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

METHODS

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

SEE ALSO

330       Test::MockObject::Extends
331
332       Sub::Override
333

AUTHORS

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)
Impressum