1Test::MockModule(3) User Contributed Perl Documentation Test::MockModule(3)
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
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
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
272 Test::MockObject::Extends
273
274 Sub::Override
275
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)