1Test::Spec::Mocks(3)  User Contributed Perl Documentation Test::Spec::Mocks(3)
2
3
4

NAME

6       Test::Spec::Mocks - Object Simulation Plugin for Test::Spec
7

SYNOPSIS

9         use Test::Spec;
10         use base qw(Test::Spec);
11
12         use My::RSS::Tool;    # this is what we're testing
13         use LWP::UserAgent;
14
15         describe "RSS tool" => sub {
16           it "should fetch and parse an RSS feed" => sub {
17             my $xml = load_rss_fixture();
18             LWP::Simple->expects('get')->returns($xml);
19
20             # calls LWP::Simple::get, but returns our $xml instead
21             my @stories = My::RSS::Tool->run;
22
23             is_deeply(\@stories, load_stories_fixture());
24           };
25         };
26

DESCRIPTION

28       Test::Spec::Mocks is a plugin for Test::Spec that provides mocking and
29       stubbing of objects, individual methods and plain subroutines on both
30       object instances and classes. This module is inspired by and heavily
31       borrows from Mocha, a library for the Ruby programming language. Mocha
32       itself is inspired by JMock.
33
34       Mock objects provide a way to simulate the behavior of real objects,
35       while providing consistent, repeatable results. This is very useful
36       when you need to test a function whose results are dependent upon an
37       external factor that is normally uncontrollable (like the time of day).
38       Mocks also allow you to test your code in isolation, a tenet of unit
39       testing.
40
41       There are many other reasons why mock objects might come in handy. See
42       the Mock objects <http://en.wikipedia.org/wiki/Mock_object> article at
43       Wikipedia for lots more examples and more in-depth coverage of the
44       philosophy behind object mocking.
45
46   Ecosystem
47       Test::Spec::Mocks is currently only usable from within tests built with
48       the Test::Spec BDD framework.
49
50   Terminology
51       Familiarize yourself with these terms:
52
53       •   Stub object
54
55           A stub object is an object created specifically to return canned
56           responses for a specific set of methods. These are created with the
57           stub function.
58
59       •   Mock object
60
61           Mock objects are similar to stub objects, but are programmed with
62           both prepared responses and expectations for how they will be
63           called. If the expectations are not met, they raise an exception to
64           indicate that the test failed. Mock objects are created with the
65           mock function.
66
67       •   Stubbed method
68
69           Stubbed methods temporarily replace existing methods on a class or
70           object instance. This is useful when you only want to override a
71           subset of an object or class's behavior. For example, you might
72           want to override the "do" method of a DBI handle so it doesn't make
73           changes to your database, but still need the handle to respond as
74           usual to the "quote" method.  You'll stub methods using the stubs
75           method.
76
77       •   Mocked method
78
79           If you've been reading up to this point, this will be no surprise.
80           Mocked methods are just like stubbed methods, but they come with
81           expectations that will raise an exception if not met. For example,
82           you can mock a "save" method on an object to ensure it is called by
83           the code you are testing, while preventing the data from actually
84           being committed to disk in your test. Use the expects method to
85           create mock methods.
86
87       •   "stub", "mock"
88
89           Depending on context, these can refer to stubbed objects and
90           methods, or mocked objects and methods, respectively.
91
92   Using stub objects (anonymous stubs)
93       Sometimes the code you're testing requires that you pass it an object
94       that conforms to a specific interface. For example, you are testing a
95       console prompting library, but you don't want to require a real person
96       to stand by, waiting to type answers into the console. The library
97       requires an object that returns a string when the "read_line" method is
98       called.
99
100       You could create a class specifically for returning test console input.
101       But why do that? You can create a stub object in one line:
102
103         describe "An Asker" => sub {
104           my $asker = Asker->new;
105
106           it "returns true when a yes_or_no question is answered 'yes'" => sub {
107             my $console_stub = stub(read_line => "yes");
108             # $console_stub->read_line returns "yes"
109             ok( $asker->yes_or_no($console_stub, "Am I awesome?") );
110           };
111
112           it "returns false when a yes_or_no question is answered 'no'" => sub {
113             my $console_stub = stub(read_line => "no");
114             ok( ! $asker->yes_or_no($console_stub, "Am I second best?") );
115           };
116         };
117
118       Stubs can also take subroutine references.  This is useful when the
119       behavior you need to mimic is a little more complex.
120
121         it "keeps asking until it gets an answer" => sub {
122           my @answers = (undef, "yes");
123           my $console_stub = stub(read_line => sub { shift @answers });
124           # when console_stub is called the first time, it returns undef
125           # the second time returns "yes"
126           ok( $asker->yes_or_no($console_stub, "Do I smell nice?") );
127         };
128
129   Using mock objects
130       If you want to take your tests one step further, you can use mock
131       objects instead of stub objects. Mocks ensure the methods you expect to
132       be called actually are called. If they aren't, the mock will raise an
133       exception which causes your test to fail.
134
135       In this example, we are testing that "read_line" is called once and
136       only once (the default for mocks).
137
138         it "returns true when a yes_or_no question is answered 'yes'" => sub {
139           my $console_mock = mock();
140           $console_mock->expects('read_line')
141                        ->returns("yes");
142           # $console_mock->read_line returns "yes"
143           ok( $asker->yes_or_no($console_mock, "Am I awesome?") );
144         };
145
146       If Asker's "yes_or_no" method doesn't call "read_line" on our mock
147       exactly one time, the test would fail with a message like:
148
149         expected read_line to be called exactly 1 time, but it was called 0 times
150
151       You can specify how many times your mock should be called with
152       "exactly":
153
154         it "keeps asking until it gets an answer" => sub {
155           my @answers = (undef, "yes");
156           my $console_mock = mock();
157           $console_mock->expects('read_line')
158                        ->returns(sub { shift @answers })
159                        ->exactly(2);
160           # when console_mock is called the first time, it returns undef
161           # the second time returns "yes"
162           ok( $asker->yes_or_no($console_mock, "Do I smell nice?") );
163         };
164
165       If you want something more flexible than "exactly", you can choose from
166       "at_least", "at_most", "any_number" and others. See "EXPECTATION
167       ADJUSTMENT METHODS".
168
169   Stubbing methods
170       Sometimes you want to override just a small subset of an object's
171       behavior.
172
173         describe "The old audit system" => sub {
174           my $dbh;
175           before sub { $dbh = SomeExternalClass->get_dbh };
176
177           it "executes the expected sql" => sub {
178             my $sql;
179             $dbh->stubs(do => sub { $sql = shift; return 1 });
180
181             # $dbh->do("foo") now sets $sql to "foo"
182             # $dbh->quote still does what it normally would
183
184             audit_event($dbh, "server crash, oh noes!!");
185
186             like( $sql, qr/insert into audit_event.*'server crash, oh noes!!!'/ );
187           };
188         };
189
190       You can also stub class methods:
191
192         # 1977-05-26T14:11:55
193         my $event_datetime = DateTime->new(from_epoch => 0xdeafcab);
194
195         it "should tag each audit event with the current time" => sub {
196           DateTime->stubs('now' => sub { $event_datetime });
197           is( audit_timestamp(), '19770526.141155' );
198         };
199
200   Mocking methods
201       Mocked methods are to stubbed methods as mock objects are to stub
202       objects.
203
204         it "executes the expected sql" => sub {
205           $dbh->expects('do')->returns(sub { $sql = shift; return 1 });
206
207           # $dbh->do("foo") now sets $sql to "foo"
208           # $dbh->quote still does what it normally would
209
210           audit_event($dbh, "server crash, oh noes!!");
211           like( $sql, qr/insert into audit_event.*'server crash, oh noes!!!'/ );
212
213           # if audit_event doesn't call $dbh->do exactly once, KABOOM!
214         };
215

CONSTRUCTORS

217       stub()
218       stub($method_name => $result, ...)
219       stub($method_name => sub { $result }, ...)
220       stub({ $method_name => $result, ... })
221           Returns a new anonymous stub object. Takes a list of
222           $method_name/$result pairs or a reference to a hash containing the
223           same.  Each $method_name listed is stubbed to return the associated
224           value ($result); or if the value is a subroutine reference, it is
225           stubbed in-place (the subroutine becomes the method).
226
227           Examples:
228
229             # A blank object with no methods.
230             # Gives a true response to ref() and blessed().
231             my $blank = stub();
232
233             # Static responses to width() and height():
234             my $rect = stub(width => 5, height => 5);
235
236             # Dynamic response to area():
237             my $radius = 1.0;
238             my $circle_stub = stub(area => sub { PI * $radius * $radius });
239
240           You can also stub more methods, just like with any other object:
241
242             my $rect = stub(width => 5, height => 5);
243             $rect->stubs(area => sub { my $self = shift; $self->width * $self->height });
244
245       $thing->stubs($method_name)
246       $thing->stubs($method_name => $result)
247       $thing->stubs($method_name => sub { $result })
248       $thing->stubs({ $method_name => $result })
249           Stubs one or more methods on an existing class or instance, $thing.
250
251           If passed only one (non-hash) argument, it is interpreted as a
252           method name.  The return value of the stubbed method will be
253           "undef".
254
255           Otherwise, the arguments are a list of $method_name and $result
256           pairs, either as a flat list or as a hash reference. Each method is
257           installed onto $thing, and returns the specified result. If the
258           result is a subroutine reference, it will be called for every
259           invocation of the method.
260
261       mock()
262           Returns a new blank, anonymous mock object, suitable for mocking
263           methods with expects().
264
265             my $rect = mock();
266             $rect->expects('area')->returns(100);
267
268       $thing->expects($method)
269           Installs a mock method named $method onto the class or object
270           $thing and returns an Test::Spec::Mocks::Expectation object, which
271           you can use to set the return value with returns() and other
272           expectations. By default, the method is expected to be called
273           at_least_once.
274
275           If the expectation is not met before the enclosing example
276           completes, the mocked method will raise an exception that looks
277           something like:
278
279             expected foo to be called exactly 1 time, but it was called 0 times
280

EXPECTATION ADJUSTMENT METHODS

282       These are methods of the Test::Spec::Mocks::Expectation class, which
283       you'll receive by calling expects() on a class or object instance.
284
285       returns( $result )
286       returns( @result )
287       returns( \&callback )
288           Configures the mocked method to return the specified result when
289           called. If passed a subroutine reference, the subroutine will be
290           executed when the method is called, and the result is the return
291           value.
292
293             $rect->expects('height')->returns(5);
294             # $rect->height ==> 5
295
296             @points = ( [0,0], [1,0], [1,1], [1,0] );
297             $rect->expects('points')->returns(@points);
298             # (@p = $rect->points) ==> ( [0,0], [1,0], [1,1], [1,0] )
299             # ($p = $rect->points) ==> 4
300
301             @points = ( [0,0], [1,0], [1,1], [1,0] );
302             $rect->expects('next_point')->returns(sub { shift @points });
303             # $rect->next_point ==> [0,0]
304             # $rect->next_point ==> [1,0]
305             # ...
306
307       exactly($N)
308           Configures the mocked method so that it must be called exactly $N
309           times.
310
311       never
312           Configures the mocked method so that it must never be called.
313
314       once
315           Configures the mocked method so that it must be called exactly one
316           time.
317
318       at_least($N)
319           Configures the mocked method so that it must be called at least $N
320           times.
321
322       at_least_once
323           Configures the mocked method so that it must be called at least 1
324           time.  This is just syntactic sugar for at_least(1).
325
326       at_most($N)
327           Configures the mocked method so that it must be called no more than
328           $N times.
329
330       at_most_once
331           Configures the mocked method so that it must be called either zero
332           or 1 times.
333
334       maybe
335           An alias for "at_most_once".
336
337       any_number
338           Configures the mocked method so that it can be called zero or more
339           times.
340
341       times
342           A syntactic sugar no-op:
343
344             $io->expects('print')->exactly(3)->times;
345
346           This method is alpha and will probably change in a future release.
347
348       with(@arguments) / with_eq(@arguments)
349           Configures the mocked method so that it must be called with
350           arguments as specified. The arguments will be compared using the
351           "eq" operator, so it works for most scalar values with no problem.
352           If you want to check objects here, they must be the exact same
353           instance or you must overload the "eq" operator to provide the
354           behavior you desire.
355
356       with_deep(@arguments)
357           Similar to "with_eq" except the arguments are compared using
358           Test::Deep: scalars are compared by value, arrays and hashes must
359           have the same elements and references must be blessed into the same
360           class.
361
362               $cache->expects('set')
363                     ->with_deep($customer_id, { name => $customer_name });
364
365           Use Test::Deep's comparison functions for more flexibility:
366
367               use Test::Deep::NoTest ();
368               $s3->expects('put')
369                  ->with_deep('test-bucket', 'my-doc', Test::Deep::ignore());
370
371       raises($exception)
372           Configures the mocked method so that it raises $exception when
373           called.
374

OTHER EXPECTATION METHODS

376       verify
377           Allows you to verify manually that the expectation was met. If the
378           expectation has not been met, the method dies with an error message
379           containing specifics of the failure.  Returns true otherwise.
380
381       problems
382           If the expectation has not been met, returns a list of problem
383           description strings. Otherwise, returns an empty list.
384

KNOWN ISSUES

386       Memory leaks
387           Because of the way the mock objects ("stubs", "stub", "expects",
388           and "mock") are integrated into the Test::Spec runtime they will
389           leak memory. It is not recommended to use the Test::Spec mocks in
390           any long-running program.
391
392           Patches welcome.
393

SEE ALSO

395       There are other less sugary mocking systems for Perl, including
396       Test::MockObject and Test::MockObject::Extends.
397
398       This module is a plugin for Test::Spec.  It is inspired by Mocha
399       <http://mocha.rubyforge.org/>.
400
401       The Wikipedia article Mock object
402       <http://en.wikipedia.org/wiki/Mock_object> is very informative.
403

AUTHOR

405       Philip Garrett, <philip.garrett@icainformatics.com>
406
408       Copyright (c) 2011 by Informatics Corporation of America.
409
410       This program is free software; you can redistribute it and/or modify it
411       under the same terms as Perl itself.
412
413
414
415perl v5.36.0                      2023-01-20              Test::Spec::Mocks(3)
Impressum