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
22 Module::Name::subroutine(@args); # original subroutine
23
24 # Working with objects
25 use Foo;
26 use Test::MockModule;
27 {
28 my $mock = Test::MockModule->new('Foo');
29 $mock->mock(foo => sub { print "Foo!\n"; });
30
31 my $foo = Foo->new();
32 $foo->foo(); # prints "Foo!\n"
33 }
34
36 "Test::MockModule" lets you temporarily redefine subroutines in other
37 packages for the purposes of unit testing.
38
39 A "Test::MockModule" object is set up to mock subroutines for a given
40 module. The object remembers the original subroutine so it can be
41 easily restored. This happens automatically when all MockModule objects
42 for the given module go out of scope, or when you "unmock()" the
43 subroutine.
44
46 new($package[, %options])
47 Returns an object that will mock subroutines in the specified
48 $package.
49
50 If there is no $VERSION defined in $package, the module will be
51 automatically loaded. You can override this behaviour by setting
52 the "no_auto" option:
53
54 my $mock = Test::MockModule->new('Module::Name', no_auto => 1);
55
56 get_package()
57 Returns the target package name for the mocked subroutines
58
59 is_mocked($subroutine)
60 Returns a boolean value indicating whether or not the subroutine is
61 currently mocked
62
63 mock($subroutine => \&coderef)
64 Temporarily replaces one or more subroutines in the mocked module.
65 A subroutine can be mocked with a code reference or a scalar. A
66 scalar will be recast as a subroutine that returns the scalar.
67
68 The following statements are equivalent:
69
70 $module->mock(purge => 'purged');
71 $module->mock(purge => sub { return 'purged'});
72
73 When dealing with references, things behave slightly differently.
74 The following statements are NOT equivalent:
75
76 # Returns the same arrayref each time, with the localtime() at time of mocking
77 $module->mock(updated => [localtime()]);
78 # Returns a new arrayref each time, with up-to-date localtime() value
79 $module->mock(updated => sub { return [localtime()]});
80
81 The following statements are in fact equivalent:
82
83 my $array_ref = [localtime()]
84 $module->mock(updated => $array_ref)
85 $module->mock(updated => sub { return $array_ref });
86
87 However, "undef" is a special case. If you mock a subroutine with
88 "undef" it will install an empty subroutine
89
90 $module->mock(purge => undef);
91 $module->mock(purge => sub { });
92
93 rather than a subroutine that returns "undef":
94
95 $module->mock(purge => sub { undef });
96
97 You can call "mock()" for the same subroutine many times, but when
98 you call "unmock()", the original subroutine is restored (not the
99 last mocked instance).
100
101 MOCKING + EXPORT
102
103 If you are trying to mock a subroutine exported from another
104 module, this may not behave as you initially would expect, since
105 Test::MockModule is only mocking at the target module, not anything
106 importing that module. If you mock the local package, or use a
107 fully qualified function name, you will get the behavior you
108 desire:
109
110 use Test::MockModule;
111 use Test::More;
112 use POSIX qw/strftime/;
113
114 my $posix = Test::MockModule->new("POSIX");
115
116 $posix->mock("strftime", "Yesterday");
117 is strftime("%D", localtime(time)), "Yesterday", "`strftime` was mocked successfully"; # Fails
118 is POSIX::strftime("%D", localtime(time)), "Yesterday", "`strftime` was mocked successfully"; # Succeeds
119
120 my $main = Test::MockModule->new("main", no_auto => 1);
121 $main->mock("strftime", "today");
122 is strftime("%D", localtime(time)), "today", "`strftime` was mocked successfully"; # Succeeds
123
124 If you are trying to mock a subroutine that was exported into a
125 module that you're trying to test, rather than mocking the
126 subroutine in its originating module, you can instead mock it in
127 the module you are testing:
128
129 package MyModule;
130 use POSIX qw/strftime/;
131
132 sub minus_twentyfour
133 {
134 return strftime("%a, %b %d, %Y", localtime(time - 86400));
135 }
136
137 package main;
138 use Test::More;
139 use Test::MockModule;
140
141 my $posix = Test::MockModule->new("POSIX");
142 $posix->mock("strftime", "Yesterday");
143
144 is MyModule::minus_twentyfour(), "Yesterday", "`minus-twentyfour` got mocked"; # fails
145
146 my $mymodule = Test::MockModule->new("MyModule", no_auto => 1);
147 $mymodule->mock("strftime", "Yesterday");
148 is MyModule::minus_twentyfour(), "Yesterday", "`minus-twentyfour` got mocked"; # succeeds
149
150 redefine($subroutine)
151 The same behavior as "mock()", but this will preemptively check to
152 be sure that all passed subroutines actually exist. This is useful
153 to ensure that if a mocked module's interface changes the test
154 doesn't just keep on testing a code path that no longer behaves
155 consistently with the mocked behavior.
156
157 Note that redefine is also now checking if one of the parent
158 provides the sub and will not die if it's available in the chain.
159
160 original($subroutine)
161 Returns the original (unmocked) subroutine
162
163 Here is a sample how to wrap a function with custom arguments using
164 the original subroutine. This is useful when you cannot (do not)
165 want to alter the original code to abstract one hardcoded argument
166 pass to a function.
167
168 package MyModule;
169
170 sub sample {
171 return get_path_for("/a/b/c/d");
172 }
173
174 sub get_path_for {
175 ... # anything goes there...
176 }
177
178 package main;
179 use Test::MockModule;
180
181 my $mock = Test::MockModule->new("MyModule");
182 # replace all calls to get_path_for using a different argument
183 $mock->redefine("get_path_for", sub {
184 return $mock->original("get_path_for")->("/my/custom/path");
185 });
186
187 # or
188
189 $mock->redefine("get_path_for", sub {
190 my $path = shift;
191 if ( $path && $path eq "/a/b/c/d" ) {
192 # only alter calls with path set to "/a/b/c/d"
193 return $mock->original("get_path_for")->("/my/custom/path");
194 } else { # preserve the original arguments
195 return $mock->original("get_path_for")->(@_);
196 }
197 });
198
199 unmock($subroutine [, ...])
200 Restores the original $subroutine. You can specify a list of
201 subroutines to "unmock()" in one go.
202
203 unmock_all()
204 Restores all the subroutines in the package that were mocked. This
205 is automatically called when all "Test::MockObject" objects for the
206 given package go out of scope.
207
208 noop($subroutine [, ...])
209 Given a list of subroutine names, mocks each of them with a no-op
210 subroutine. Handy for mocking methods you want to ignore!
211
212 # Neuter a list of methods in one go
213 $module->noop('purge', 'updated');
214
215 TRACE
216 A stub for Log::Trace
217
218 DUMP
219 A stub for Log::Trace
220
222 Test::MockObject::Extends
223
224 Sub::Override
225
227 Current Maintainer: Geoff Franks <gfranks@cpan.org>
228
229 Original Author: Simon Flack <simonflk _AT_ cpan.org>
230
232 Copyright 2004 Simon Flack <simonflk _AT_ cpan.org>. All rights
233 reserved
234
235 You may distribute under the terms of either the GNU General Public
236 License or the Artistic License, as specified in the Perl README file.
237
238
239
240perl v5.30.0 2019-07-26 Test::MockModule(3)