| 148 |
lars |
1 |
.. index::
|
|
|
2 |
single: Mocking; Partial Mocks
|
|
|
3 |
|
|
|
4 |
Creating Partial Mocks
|
|
|
5 |
======================
|
|
|
6 |
|
|
|
7 |
Partial mocks are useful when we only need to mock several methods of an
|
|
|
8 |
object leaving the remainder free to respond to calls normally (i.e. as
|
|
|
9 |
implemented). Mockery implements three distinct strategies for creating
|
|
|
10 |
partials. Each has specific advantages and disadvantages so which strategy we
|
|
|
11 |
use will depend on our own preferences and the source code in need of
|
|
|
12 |
mocking.
|
|
|
13 |
|
|
|
14 |
We have previously talked a bit about :ref:`creating-test-doubles-partial-test-doubles`,
|
|
|
15 |
but we'd like to expand on the subject a bit here.
|
|
|
16 |
|
|
|
17 |
#. Runtime partial test doubles
|
|
|
18 |
#. Generated partial test doubles
|
|
|
19 |
#. Proxied Partial Mock
|
|
|
20 |
|
|
|
21 |
Runtime partial test doubles
|
|
|
22 |
----------------------------
|
|
|
23 |
|
|
|
24 |
A runtime partial test double, also known as a passive partial mock, is a kind
|
|
|
25 |
of a default state of being for a mocked object.
|
|
|
26 |
|
|
|
27 |
.. code-block:: php
|
|
|
28 |
|
|
|
29 |
$mock = \Mockery::mock('MyClass')->makePartial();
|
|
|
30 |
|
|
|
31 |
With a runtime partial, we assume that all methods will simply defer to the
|
|
|
32 |
parent class (``MyClass``) original methods unless a method call matches a
|
|
|
33 |
known expectation. If we have no matching expectation for a specific method
|
|
|
34 |
call, that call is deferred to the class being mocked. Since the division
|
|
|
35 |
between mocked and unmocked calls depends entirely on the expectations we
|
|
|
36 |
define, there is no need to define which methods to mock in advance.
|
|
|
37 |
|
|
|
38 |
See the cookbook entry on :doc:`../cookbook/big_parent_class` for an example
|
|
|
39 |
usage of runtime partial test doubles.
|
|
|
40 |
|
|
|
41 |
Generated Partial Test Doubles
|
|
|
42 |
------------------------------
|
|
|
43 |
|
|
|
44 |
A generated partial test double, also known as a traditional partial mock,
|
|
|
45 |
defines ahead of time which methods of a class are to be mocked and which are
|
|
|
46 |
to be left unmocked (i.e. callable as normal). The syntax for creating
|
|
|
47 |
traditional mocks is:
|
|
|
48 |
|
|
|
49 |
.. code-block:: php
|
|
|
50 |
|
|
|
51 |
$mock = \Mockery::mock('MyClass[foo,bar]');
|
|
|
52 |
|
|
|
53 |
In the above example, the ``foo()`` and ``bar()`` methods of MyClass will be
|
|
|
54 |
mocked but no other MyClass methods are touched. We will need to define
|
|
|
55 |
expectations for the ``foo()`` and ``bar()`` methods to dictate their mocked
|
|
|
56 |
behaviour.
|
|
|
57 |
|
|
|
58 |
Don't forget that we can pass in constructor arguments since unmocked methods
|
|
|
59 |
may rely on those!
|
|
|
60 |
|
|
|
61 |
.. code-block:: php
|
|
|
62 |
|
|
|
63 |
$mock = \Mockery::mock('MyNamespace\MyClass[foo]', array($arg1, $arg2));
|
|
|
64 |
|
|
|
65 |
See the :ref:`creating-test-doubles-constructor-arguments` section to read up
|
|
|
66 |
on them.
|
|
|
67 |
|
|
|
68 |
.. note::
|
|
|
69 |
|
|
|
70 |
Even though we support generated partial test doubles, we do not recommend
|
|
|
71 |
using them.
|
|
|
72 |
|
|
|
73 |
Proxied Partial Mock
|
|
|
74 |
--------------------
|
|
|
75 |
|
|
|
76 |
A proxied partial mock is a partial of last resort. We may encounter a class
|
|
|
77 |
which is simply not capable of being mocked because it has been marked as
|
|
|
78 |
final. Similarly, we may find a class with methods marked as final. In such a
|
|
|
79 |
scenario, we cannot simply extend the class and override methods to mock - we
|
|
|
80 |
need to get creative.
|
|
|
81 |
|
|
|
82 |
.. code-block:: php
|
|
|
83 |
|
|
|
84 |
$mock = \Mockery::mock(new MyClass);
|
|
|
85 |
|
|
|
86 |
Yes, the new mock is a Proxy. It intercepts calls and reroutes them to the
|
|
|
87 |
proxied object (which we construct and pass in) for methods which are not
|
|
|
88 |
subject to any expectations. Indirectly, this allows us to mock methods
|
|
|
89 |
marked final since the Proxy is not subject to those limitations. The tradeoff
|
|
|
90 |
should be obvious - a proxied partial will fail any typehint checks for the
|
|
|
91 |
class being mocked since it cannot extend that class.
|
|
|
92 |
|
|
|
93 |
Special Internal Cases
|
|
|
94 |
----------------------
|
|
|
95 |
|
|
|
96 |
All mock objects, with the exception of Proxied Partials, allows us to make
|
|
|
97 |
any expectation call to the underlying real class method using the ``passthru()``
|
|
|
98 |
expectation call. This will return values from the real call and bypass any
|
|
|
99 |
mocked return queue (which can simply be omitted obviously).
|
|
|
100 |
|
|
|
101 |
There is a fourth kind of partial mock reserved for internal use. This is
|
|
|
102 |
automatically generated when we attempt to mock a class containing methods
|
|
|
103 |
marked final. Since we cannot override such methods, they are simply left
|
|
|
104 |
unmocked. Typically, we don't need to worry about this but if we really
|
|
|
105 |
really must mock a final method, the only possible means is through a Proxied
|
|
|
106 |
Partial Mock. SplFileInfo, for example, is a common class subject to this form
|
|
|
107 |
of automatic internal partial since it contains public final methods used
|
|
|
108 |
internally.
|