1Test::MockModule(3)   User Contributed Perl Documentation  Test::MockModule(3)
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

DESCRIPTION

60       "Test::MockModule" lets you temporarily redefine subroutines in other
61       packages for the purposes of unit testing.
62
63       A "Test::MockModule" object is set up to mock subroutines for a given
64       module. The object remembers the original subroutine so it can be
65       easily restored. This happens automatically when all MockModule objects
66       for the given module go out of scope, or when you "unmock()" the
67       subroutine.
68

METHODS

70       new($package[, %options])
71           Returns an object that will mock subroutines in the specified
72           $package.
73
74           If there is no $VERSION defined in $package, the module will be
75           automatically loaded. You can override this behaviour by setting
76           the "no_auto" option:
77
78                   my $mock = Test::MockModule->new('Module::Name', no_auto => 1);
79
80       get_package()
81           Returns the target package name for the mocked subroutines
82
83       is_mocked($subroutine)
84           Returns a boolean value indicating whether or not the subroutine is
85           currently mocked
86
87       mock($subroutine => \&coderef)
88           Temporarily replaces one or more subroutines in the mocked module.
89           A subroutine can be mocked with a code reference or a scalar. A
90           scalar will be recast as a subroutine that returns the scalar.
91
92           Returns the current "Test::MockModule" object, so you can chain new
93           with mock.
94
95                   my $mock = Test::MockModule->new->(...)->mock(...);
96
97           The following statements are equivalent:
98
99                   $module->mock(purge => 'purged');
100                   $module->mock(purge => sub { return 'purged'});
101
102           When dealing with references, things behave slightly differently.
103           The following statements are NOT equivalent:
104
105                   # Returns the same arrayref each time, with the localtime() at time of mocking
106                   $module->mock(updated => [localtime()]);
107                   # Returns a new arrayref each time, with up-to-date localtime() value
108                   $module->mock(updated => sub { return [localtime()]});
109
110           The following statements are in fact equivalent:
111
112                   my $array_ref = [localtime()]
113                   $module->mock(updated => $array_ref)
114                   $module->mock(updated => sub { return $array_ref });
115
116           However, "undef" is a special case. If you mock a subroutine with
117           "undef" it will install an empty subroutine
118
119                   $module->mock(purge => undef);
120                   $module->mock(purge => sub { });
121
122           rather than a subroutine that returns "undef":
123
124                   $module->mock(purge => sub { undef });
125
126           You can call "mock()" for the same subroutine many times, but when
127           you call "unmock()", the original subroutine is restored (not the
128           last mocked instance).
129
130           MOCKING + EXPORT
131
132           If you are trying to mock a subroutine exported from another
133           module, this may not behave as you initially would expect, since
134           Test::MockModule is only mocking at the target module, not anything
135           importing that module. If you mock the local package, or use a
136           fully qualified function name, you will get the behavior you
137           desire:
138
139                   use Test::MockModule;
140                   use Test::More;
141                   use POSIX qw/strftime/;
142
143                   my $posix = Test::MockModule->new("POSIX");
144
145                   $posix->mock("strftime", "Yesterday");
146                   is strftime("%D", localtime(time)), "Yesterday", "`strftime` was mocked successfully"; # Fails
147                   is POSIX::strftime("%D", localtime(time)), "Yesterday", "`strftime` was mocked successfully"; # Succeeds
148
149                   my $main = Test::MockModule->new("main", no_auto => 1);
150                   $main->mock("strftime", "today");
151                   is strftime("%D", localtime(time)), "today", "`strftime` was mocked successfully"; # Succeeds
152
153           If you are trying to mock a subroutine that was exported into a
154           module that you're trying to test, rather than mocking the
155           subroutine in its originating module, you can instead mock it in
156           the module you are testing:
157
158                   package MyModule;
159                   use POSIX qw/strftime/;
160
161                   sub minus_twentyfour
162                   {
163                           return strftime("%a, %b %d, %Y", localtime(time - 86400));
164                   }
165
166                   package main;
167                   use Test::More;
168                   use Test::MockModule;
169
170                   my $posix = Test::MockModule->new("POSIX");
171                   $posix->mock("strftime", "Yesterday");
172
173                   is MyModule::minus_twentyfour(), "Yesterday", "`minus-twentyfour` got mocked"; # fails
174
175                   my $mymodule = Test::MockModule->new("MyModule", no_auto => 1);
176                   $mymodule->mock("strftime", "Yesterday");
177                   is MyModule::minus_twentyfour(), "Yesterday", "`minus-twentyfour` got mocked"; # succeeds
178
179       redefine($subroutine)
180           The same behavior as "mock()", but this will preemptively check to
181           be sure that all passed subroutines actually exist. This is useful
182           to ensure that if a mocked module's interface changes the test
183           doesn't just keep on testing a code path that no longer behaves
184           consistently with the mocked behavior.
185
186           Note that redefine is also now checking if one of the parent
187           provides the sub and will not die if it's available in the chain.
188
189           Returns the current "Test::MockModule" object, so you can chain new
190           with redefine.
191
192                   my $mock = Test::MockModule->new->(...)->redefine(...);
193
194       define($subroutine)
195           The reverse of redefine, this will fail if the passed subroutine
196           exists.  While this use case is rare, there are times where the
197           perl code you are testing is inspecting a package and adding a
198           missing subroutine is actually what you want to do.
199
200           By using define, you're asserting that the subroutine you want to
201           be mocked should not exist in advance.
202
203           Note: define does not check for inheritance like redefine.
204
205           Returns the current "Test::MockModule" object, so you can chain new
206           with define.
207
208                   my $mock = Test::MockModule->new->(...)->define(...);
209
210       original($subroutine)
211           Returns the original (unmocked) subroutine
212
213           Here is a sample how to wrap a function with custom arguments using
214           the original subroutine.  This is useful when you cannot (do not)
215           want to alter the original code to abstract one hardcoded argument
216           pass to a function.
217
218                   package MyModule;
219
220                   sub sample {
221                           return get_path_for("/a/b/c/d");
222                   }
223
224                   sub get_path_for {
225                           ... # anything goes there...
226                   }
227
228                   package main;
229                   use Test::MockModule;
230
231                   my $mock = Test::MockModule->new("MyModule");
232                   # replace all calls to get_path_for using a different argument
233                   $mock->redefine("get_path_for", sub {
234                           return $mock->original("get_path_for")->("/my/custom/path");
235                   });
236
237                   # or
238
239                   $mock->redefine("get_path_for", sub {
240                           my $path = shift;
241                           if ( $path && $path eq "/a/b/c/d" ) {
242                                   # only alter calls with path set to "/a/b/c/d"
243                                   return $mock->original("get_path_for")->("/my/custom/path");
244                           } else { # preserve the original arguments
245                                   return $mock->original("get_path_for")->($path, @_);
246                           }
247                   });
248
249       unmock($subroutine [, ...])
250           Restores the original $subroutine. You can specify a list of
251           subroutines to "unmock()" in one go.
252
253       unmock_all()
254           Restores all the subroutines in the package that were mocked. This
255           is automatically called when all "Test::MockObject" objects for the
256           given package go out of scope.
257
258       noop($subroutine [, ...])
259           Given a list of subroutine names, mocks each of them with a no-op
260           subroutine. Handy for mocking methods you want to ignore!
261
262               # Neuter a list of methods in one go
263               $module->noop('purge', 'updated');
264
265       TRACE
266           A stub for Log::Trace
267
268       DUMP
269           A stub for Log::Trace
270

SEE ALSO

272       Test::MockObject::Extends
273
274       Sub::Override
275

AUTHORS

277       Current Maintainer: Geoff Franks <gfranks@cpan.org>
278
279       Original Author: Simon Flack <simonflk _AT_ cpan.org>
280
282       Copyright 2004 Simon Flack <simonflk _AT_ cpan.org>.  All rights
283       reserved
284
285       You may distribute under the terms of either the GNU General Public
286       License or the Artistic License, as specified in the Perl README file.
287
288
289
290perl v5.32.0                      2020-09-18               Test::MockModule(3)
Impressum