Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
.. index::
2
    single: Expectations
3
 
4
Expectation Declarations
5
========================
6
 
7
.. note::
8
 
9
    In order for our expectations to work we MUST call ``Mockery::close()``,
10
    preferably in a callback method such as ``tearDown`` or ``_after``
11
    (depending on whether or not we're integrating Mockery with another
12
    framework). This static call cleans up the Mockery container used by the
13
    current test, and run any verification tasks needed for our expectations.
14
 
15
Once we have created a mock object, we'll often want to start defining how
16
exactly it should behave (and how it should be called). This is where the
17
Mockery expectation declarations take over.
18
 
19
Declaring Method Call Expectations
20
----------------------------------
21
 
22
To tell our test double to expect a call for a method with a given name, we use
23
the ``shouldReceive`` method:
24
 
25
.. code-block:: php
26
 
27
    $mock = \Mockery::mock('MyClass');
28
    $mock->shouldReceive('name_of_method');
29
 
30
This is the starting expectation upon which all other expectations and
31
constraints are appended.
32
 
33
We can declare more than one method call to be expected:
34
 
35
.. code-block:: php
36
 
37
    $mock = \Mockery::mock('MyClass');
38
    $mock->shouldReceive('name_of_method_1', 'name_of_method_2');
39
 
40
All of these will adopt any chained expectations or constraints.
41
 
42
It is possible to declare the expectations for the method calls, along with
43
their return values:
44
 
45
.. code-block:: php
46
 
47
    $mock = \Mockery::mock('MyClass');
48
    $mock->shouldReceive([
49
        'name_of_method_1' => 'return value 1',
50
        'name_of_method_2' => 'return value 2',
51
    ]);
52
 
53
There's also a shorthand way of setting up method call expectations and their
54
return values:
55
 
56
.. code-block:: php
57
 
58
    $mock = \Mockery::mock('MyClass', ['name_of_method_1' => 'return value 1', 'name_of_method_2' => 'return value 2']);
59
 
60
All of these will adopt any additional chained expectations or constraints.
61
 
62
We can declare that a test double should not expect a call to the given method
63
name:
64
 
65
.. code-block:: php
66
 
67
    $mock = \Mockery::mock('MyClass');
68
    $mock->shouldNotReceive('name_of_method');
69
 
70
This method is a convenience method for calling ``shouldReceive()->never()``.
71
 
72
Declaring Method Argument Expectations
73
--------------------------------------
74
 
75
For every method we declare expectation for, we can add constraints that the
76
defined expectations apply only to the method calls that match the expected
77
argument list:
78
 
79
.. code-block:: php
80
 
81
    $mock = \Mockery::mock('MyClass');
82
    $mock->shouldReceive('name_of_method')
83
        ->with($arg1, $arg2, ...);
84
    // or
85
    $mock->shouldReceive('name_of_method')
86
        ->withArgs([$arg1, $arg2, ...]);
87
 
88
We can add a lot more flexibility to argument matching using the built in
89
matcher classes (see later). For example, ``\Mockery::any()`` matches any
90
argument passed to that position in the ``with()`` parameter list. Mockery also
91
allows Hamcrest library matchers - for example, the Hamcrest function
92
``anything()`` is equivalent to ``\Mockery::any()``.
93
 
94
It's important to note that this means all expectations attached only apply to
95
the given method when it is called with these exact arguments:
96
 
97
.. code-block:: php
98
 
99
    $mock = \Mockery::mock('MyClass');
100
 
101
    $mock->shouldReceive('foo')->with('Hello');
102
 
103
    $mock->foo('Goodbye'); // throws a NoMatchingExpectationException
104
 
105
This allows for setting up differing expectations based on the arguments
106
provided to expected calls.
107
 
108
Argument matching with closures
109
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
110
 
111
Instead of providing a built-in matcher for each argument, we can provide a
112
closure that matches all passed arguments at once:
113
 
114
.. code-block:: php
115
 
116
    $mock = \Mockery::mock('MyClass');
117
    $mock->shouldReceive('name_of_method')
118
        ->withArgs(closure);
119
 
120
The given closure receives all the arguments passed in the call to the expected
121
method. In this way, this expectation only applies to method calls where passed
122
arguments make the closure evaluate to true:
123
 
124
.. code-block:: php
125
 
126
    $mock = \Mockery::mock('MyClass');
127
 
128
    $mock->shouldReceive('foo')->withArgs(function ($arg) {
129
        if ($arg % 2 == 0) {
130
            return true;
131
        }
132
        return false;
133
    });
134
 
135
    $mock->foo(4); // matches the expectation
136
    $mock->foo(3); // throws a NoMatchingExpectationException
137
 
138
Argument matching with some of given values
139
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
140
 
141
We can provide expected arguments that match passed arguments when mocked method
142
is called.
143
 
144
.. code-block:: php
145
 
146
    $mock = \Mockery::mock('MyClass');
147
    $mock->shouldReceive('name_of_method')
148
        ->withSomeOfArgs(arg1, arg2, arg3, ...);
149
 
150
The given expected arguments order doesn't matter.
151
Check if expected values are included or not, but type should be matched:
152
 
153
.. code-block:: php
154
 
155
    $mock = \Mockery::mock('MyClass');
156
    $mock->shouldReceive('foo')
157
        ->withSomeOfArgs(1, 2);
158
 
159
    $mock->foo(1, 2, 3);  // matches the expectation
160
    $mock->foo(3, 2, 1);  // matches the expectation (passed order doesn't matter)
161
    $mock->foo('1', '2'); // throws a NoMatchingExpectationException (type should be matched)
162
    $mock->foo(3);        // throws a NoMatchingExpectationException
163
 
164
Any, or no arguments
165
^^^^^^^^^^^^^^^^^^^^
166
 
167
We can declare that the expectation matches a method call regardless of what
168
arguments are passed:
169
 
170
.. code-block:: php
171
 
172
    $mock = \Mockery::mock('MyClass');
173
    $mock->shouldReceive('name_of_method')
174
        ->withAnyArgs();
175
 
176
This is set by default unless otherwise specified.
177
 
178
We can declare that the expectation matches method calls with zero arguments:
179
 
180
.. code-block:: php
181
 
182
    $mock = \Mockery::mock('MyClass');
183
    $mock->shouldReceive('name_of_method')
184
        ->withNoArgs();
185
 
186
Declaring Return Value Expectations
187
-----------------------------------
188
 
189
For mock objects, we can tell Mockery what return values to return from the
190
expected method calls.
191
 
192
For that we can use the ``andReturn()`` method:
193
 
194
.. code-block:: php
195
 
196
    $mock = \Mockery::mock('MyClass');
197
    $mock->shouldReceive('name_of_method')
198
        ->andReturn($value);
199
 
200
This sets a value to be returned from the expected method call.
201
 
202
It is possible to set up expectation for multiple return values. By providing
203
a sequence of return values, we tell Mockery what value to return on every
204
subsequent call to the method:
205
 
206
.. code-block:: php
207
 
208
    $mock = \Mockery::mock('MyClass');
209
    $mock->shouldReceive('name_of_method')
210
        ->andReturn($value1, $value2, ...)
211
 
212
The first call will return ``$value1`` and the second call will return ``$value2``.
213
 
214
If we call the method more times than the number of return values we declared,
215
Mockery will return the final value for any subsequent method call:
216
 
217
.. code-block:: php
218
 
219
    $mock = \Mockery::mock('MyClass');
220
 
221
    $mock->shouldReceive('foo')->andReturn(1, 2, 3);
222
 
223
    $mock->foo(); // int(1)
224
    $mock->foo(); // int(2)
225
    $mock->foo(); // int(3)
226
    $mock->foo(); // int(3)
227
 
228
The same can be achieved using the alternative syntax:
229
 
230
.. code-block:: php
231
 
232
    $mock = \Mockery::mock('MyClass');
233
    $mock->shouldReceive('name_of_method')
234
        ->andReturnValues([$value1, $value2, ...])
235
 
236
It accepts a simple array instead of a list of parameters. The order of return
237
is determined by the numerical index of the given array with the last array
238
member being returned on all calls once previous return values are exhausted.
239
 
240
The following two options are primarily for communication with test readers:
241
 
242
.. code-block:: php
243
 
244
    $mock = \Mockery::mock('MyClass');
245
    $mock->shouldReceive('name_of_method')
246
        ->andReturnNull();
247
    // or
248
    $mock->shouldReceive('name_of_method')
249
        ->andReturn([null]);
250
 
251
They mark the mock object method call as returning ``null`` or nothing.
252
 
253
Sometimes we want to calculate the return results of the method calls, based on
254
the arguments passed to the method. We can do that with the ``andReturnUsing()``
255
method which accepts one or more closure:
256
 
257
.. code-block:: php
258
 
259
    $mock = \Mockery::mock('MyClass');
260
    $mock->shouldReceive('name_of_method')
261
        ->andReturnUsing(closure, ...);
262
 
263
Closures can be queued by passing them as extra parameters as for ``andReturn()``.
264
 
265
Occasionally, it can be useful to echo back one of the arguments that a method
266
is called with. In this case we can use the ``andReturnArg()`` method; the
267
argument to be returned is specified by its index in the arguments list:
268
 
269
.. code-block:: php
270
 
271
    $mock = \Mockery::mock('MyClass');
272
    $mock->shouldReceive('name_of_method')
273
        ->andReturnArg(1);
274
 
275
This returns the second argument (index #1) from the list of arguments when the
276
method is called.
277
 
278
.. note::
279
 
280
    We cannot currently mix ``andReturnUsing()`` or ``andReturnArg`` with
281
    ``andReturn()``.
282
 
283
If we are mocking fluid interfaces, the following method will be helpful:
284
 
285
.. code-block:: php
286
 
287
    $mock = \Mockery::mock('MyClass');
288
    $mock->shouldReceive('name_of_method')
289
        ->andReturnSelf();
290
 
291
It sets the return value to the mocked class name.
292
 
293
Throwing Exceptions
294
-------------------
295
 
296
We can tell the method of mock objects to throw exceptions:
297
 
298
.. code-block:: php
299
 
300
    $mock = \Mockery::mock('MyClass');
301
    $mock->shouldReceive('name_of_method')
302
        ->andThrow(new Exception);
303
 
304
It will throw the given ``Exception`` object when called.
305
 
306
Rather than an object, we can pass in the ``Exception`` class, message and/or code to
307
use when throwing an ``Exception`` from the mocked method:
308
 
309
.. code-block:: php
310
 
311
    $mock = \Mockery::mock('MyClass');
312
    $mock->shouldReceive('name_of_method')
313
        ->andThrow('exception_name', 'message', 123456789);
314
 
315
.. _expectations-setting-public-properties:
316
 
317
Setting Public Properties
318
-------------------------
319
 
320
Used with an expectation so that when a matching method is called, we can cause
321
a mock object's public property to be set to a specified value, by using
322
``andSet()`` or ``set()``:
323
 
324
.. code-block:: php
325
 
326
    $mock = \Mockery::mock('MyClass');
327
    $mock->shouldReceive('name_of_method')
328
        ->andSet($property, $value);
329
    // or
330
    $mock->shouldReceive('name_of_method')
331
        ->set($property, $value);
332
 
333
In cases where we want to call the real method of the class that was mocked and
334
return its result, the ``passthru()`` method tells the expectation to bypass
335
a return queue:
336
 
337
.. code-block:: php
338
 
339
    passthru()
340
 
341
It allows expectation matching and call count validation to be applied against
342
real methods while still calling the real class method with the expected
343
arguments.
344
 
345
Declaring Call Count Expectations
346
---------------------------------
347
 
348
Besides setting expectations on the arguments of the method calls, and the
349
return values of those same calls, we can set expectations on how many times
350
should any method be called.
351
 
352
When a call count expectation is not met, a
353
``\Mockery\Expectation\InvalidCountException`` will be thrown.
354
 
355
.. note::
356
 
357
    It is absolutely required to call ``\Mockery::close()`` at the end of our
358
    tests, for example in the ``tearDown()`` method of PHPUnit. Otherwise
359
    Mockery will not verify the calls made against our mock objects.
360
 
361
We can declare that the expected method may be called zero or more times:
362
 
363
.. code-block:: php
364
 
365
    $mock = \Mockery::mock('MyClass');
366
    $mock->shouldReceive('name_of_method')
367
        ->zeroOrMoreTimes();
368
 
369
This is the default for all methods unless otherwise set.
370
 
371
To tell Mockery to expect an exact number of calls to a method, we can use the
372
following:
373
 
374
.. code-block:: php
375
 
376
    $mock = \Mockery::mock('MyClass');
377
    $mock->shouldReceive('name_of_method')
378
        ->times($n);
379
 
380
where ``$n`` is the number of times the method should be called.
381
 
382
A couple of most common cases got their shorthand methods.
383
 
384
To declare that the expected method must be called one time only:
385
 
386
.. code-block:: php
387
 
388
    $mock = \Mockery::mock('MyClass');
389
    $mock->shouldReceive('name_of_method')
390
        ->once();
391
 
392
To declare that the expected method must be called two times:
393
 
394
.. code-block:: php
395
 
396
    $mock = \Mockery::mock('MyClass');
397
    $mock->shouldReceive('name_of_method')
398
        ->twice();
399
 
400
To declare that the expected method must never be called:
401
 
402
.. code-block:: php
403
 
404
    $mock = \Mockery::mock('MyClass');
405
    $mock->shouldReceive('name_of_method')
406
        ->never();
407
 
408
Call count modifiers
409
^^^^^^^^^^^^^^^^^^^^
410
 
411
The call count expectations can have modifiers set.
412
 
413
If we want to tell Mockery the minimum number of times a method should be called,
414
we use ``atLeast()``:
415
 
416
.. code-block:: php
417
 
418
    $mock = \Mockery::mock('MyClass');
419
    $mock->shouldReceive('name_of_method')
420
        ->atLeast()
421
        ->times(3);
422
 
423
``atLeast()->times(3)`` means the call must be called at least three times
424
(given matching method args) but never less than three times.
425
 
426
Similarly, we can tell Mockery the maximum number of times a method should be
427
called, using ``atMost()``:
428
 
429
.. code-block:: php
430
 
431
    $mock = \Mockery::mock('MyClass');
432
    $mock->shouldReceive('name_of_method')
433
        ->atMost()
434
        ->times(3);
435
 
436
``atMost()->times(3)`` means the call must be called no more than three times.
437
If the method gets no calls at all, the expectation will still be met.
438
 
439
We can also set a range of call counts, using ``between()``:
440
 
441
.. code-block:: php
442
 
443
    $mock = \Mockery::mock('MyClass');
444
    $mock->shouldReceive('name_of_method')
445
        ->between($min, $max);
446
 
447
This is actually identical to using ``atLeast()->times($min)->atMost()->times($max)``
448
but is provided as a shorthand. It may be followed by a ``times()`` call with no
449
parameter to preserve the APIs natural language readability.
450
 
451
Multiple Calls with Different Expectations
452
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
453
 
454
If a method is expected to get called multiple times with different arguments
455
and/or return values we can simply repeat the expectations. The same of course
456
also works if we expect multiple calls to different methods.
457
 
458
.. code-block:: php
459
 
460
    $mock = \Mockery::mock('MyClass');
461
    // Expectations for the 1st call
462
    $mock->shouldReceive('name_of_method');
463
        ->once()
464
        ->with('arg1')
465
        ->andReturn($value1)
466
 
467
        // 2nd call to same method
468
        ->shouldReceive('name_of_method')
469
        ->once()
470
        ->with('arg2')
471
        ->andReturn($value2)
472
 
473
        // final call to another method
474
        ->shouldReceive('other_method')
475
        ->once()
476
        ->with('other')
477
        ->andReturn($value_other);
478
 
479
Expectation Declaration Utilities
480
---------------------------------
481
 
482
Declares that this method is expected to be called in a specific order in
483
relation to similarly marked methods.
484
 
485
.. code-block:: php
486
 
487
    ordered()
488
 
489
The order is dictated by the order in which this modifier is actually used when
490
setting up mocks.
491
 
492
Declares the method as belonging to an order group (which can be named or
493
numbered). Methods within a group can be called in any order, but the ordered
494
calls from outside the group are ordered in relation to the group:
495
 
496
.. code-block:: php
497
 
498
    ordered(group)
499
 
500
We can set up so that method1 is called before group1 which is in turn called
501
before method2.
502
 
503
When called prior to ``ordered()`` or ``ordered(group)``, it declares this
504
ordering to apply across all mock objects (not just the current mock):
505
 
506
.. code-block:: php
507
 
508
    globally()
509
 
510
This allows for dictating order expectations across multiple mocks.
511
 
512
The ``byDefault()`` marks an expectation as a default. Default expectations are
513
applied unless a non-default expectation is created:
514
 
515
.. code-block:: php
516
 
517
    byDefault()
518
 
519
These later expectations immediately replace the previously defined default.
520
This is useful so we can setup default mocks in our unit test ``setup()`` and
521
later tweak them in specific tests as needed.
522
 
523
Returns the current mock object from an expectation chain:
524
 
525
.. code-block:: php
526
 
527
    getMock()
528
 
529
Useful where we prefer to keep mock setups as a single statement, e.g.:
530
 
531
.. code-block:: php
532
 
533
    $mock = \Mockery::mock('foo')->shouldReceive('foo')->andReturn(1)->getMock();