| 148 |
lars |
1 |
.. index::
|
|
|
2 |
single: PHPUnit Integration
|
|
|
3 |
|
|
|
4 |
PHPUnit Integration
|
|
|
5 |
===================
|
|
|
6 |
|
|
|
7 |
Mockery was designed as a simple-to-use *standalone* mock object framework, so
|
|
|
8 |
its need for integration with any testing framework is entirely optional. To
|
|
|
9 |
integrate Mockery, we need to define a ``tearDown()`` method for our tests
|
|
|
10 |
containing the following (we may use a shorter ``\Mockery`` namespace
|
|
|
11 |
alias):
|
|
|
12 |
|
|
|
13 |
.. code-block:: php
|
|
|
14 |
|
|
|
15 |
public function tearDown() {
|
|
|
16 |
\Mockery::close();
|
|
|
17 |
}
|
|
|
18 |
|
|
|
19 |
This static call cleans up the Mockery container used by the current test, and
|
|
|
20 |
run any verification tasks needed for our expectations.
|
|
|
21 |
|
|
|
22 |
For some added brevity when it comes to using Mockery, we can also explicitly
|
|
|
23 |
use the Mockery namespace with a shorter alias. For example:
|
|
|
24 |
|
|
|
25 |
.. code-block:: php
|
|
|
26 |
|
|
|
27 |
use \Mockery as m;
|
|
|
28 |
|
|
|
29 |
class SimpleTest extends \PHPUnit\Framework\TestCase
|
|
|
30 |
{
|
|
|
31 |
public function testSimpleMock() {
|
|
|
32 |
$mock = m::mock('simplemock');
|
|
|
33 |
$mock->shouldReceive('foo')->with(5, m::any())->once()->andReturn(10);
|
|
|
34 |
|
|
|
35 |
$this->assertEquals(10, $mock->foo(5));
|
|
|
36 |
}
|
|
|
37 |
|
|
|
38 |
public function tearDown() {
|
|
|
39 |
m::close();
|
|
|
40 |
}
|
|
|
41 |
}
|
|
|
42 |
|
|
|
43 |
Mockery ships with an autoloader so we don't need to litter our tests with
|
|
|
44 |
``require_once()`` calls. To use it, ensure Mockery is on our
|
|
|
45 |
``include_path`` and add the following to our test suite's ``Bootstrap.php``
|
|
|
46 |
or ``TestHelper.php`` file:
|
|
|
47 |
|
|
|
48 |
.. code-block:: php
|
|
|
49 |
|
|
|
50 |
require_once 'Mockery/Loader.php';
|
|
|
51 |
require_once 'Hamcrest/Hamcrest.php';
|
|
|
52 |
|
|
|
53 |
$loader = new \Mockery\Loader;
|
|
|
54 |
$loader->register();
|
|
|
55 |
|
|
|
56 |
If we are using Composer, we can simplify this to including the Composer
|
|
|
57 |
generated autoloader file:
|
|
|
58 |
|
|
|
59 |
.. code-block:: php
|
|
|
60 |
|
|
|
61 |
require __DIR__ . '/../vendor/autoload.php'; // assuming vendor is one directory up
|
|
|
62 |
|
|
|
63 |
.. caution::
|
|
|
64 |
|
|
|
65 |
Prior to Hamcrest 1.0.0, the ``Hamcrest.php`` file name had a small "h"
|
|
|
66 |
(i.e. ``hamcrest.php``). If upgrading Hamcrest to 1.0.0 remember to check
|
|
|
67 |
the file name is updated for all your projects.)
|
|
|
68 |
|
|
|
69 |
To integrate Mockery into PHPUnit and avoid having to call the close method
|
|
|
70 |
and have Mockery remove itself from code coverage reports, have your test case
|
|
|
71 |
extends the ``\Mockery\Adapter\Phpunit\MockeryTestCase``:
|
|
|
72 |
|
|
|
73 |
.. code-block:: php
|
|
|
74 |
|
|
|
75 |
class MyTest extends \Mockery\Adapter\Phpunit\MockeryTestCase
|
|
|
76 |
{
|
|
|
77 |
|
|
|
78 |
}
|
|
|
79 |
|
|
|
80 |
An alternative is to use the supplied trait:
|
|
|
81 |
|
|
|
82 |
.. code-block:: php
|
|
|
83 |
|
|
|
84 |
class MyTest extends \PHPUnit\Framework\TestCase
|
|
|
85 |
{
|
|
|
86 |
use \Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
|
|
|
87 |
}
|
|
|
88 |
|
|
|
89 |
Extending ``MockeryTestCase`` or using the ``MockeryPHPUnitIntegration``
|
|
|
90 |
trait is **the recommended way** of integrating Mockery with PHPUnit,
|
|
|
91 |
since Mockery 1.0.0.
|
|
|
92 |
|
|
|
93 |
PHPUnit listener
|
|
|
94 |
----------------
|
|
|
95 |
|
|
|
96 |
Before the 1.0.0 release, Mockery provided a PHPUnit listener that would
|
|
|
97 |
call ``Mockery::close()`` for us at the end of a test. This has changed
|
|
|
98 |
significantly since the 1.0.0 version.
|
|
|
99 |
|
|
|
100 |
Now, Mockery provides a PHPUnit listener that makes tests fail if
|
|
|
101 |
``Mockery::close()`` has not been called. It can help identify tests where
|
|
|
102 |
we've forgotten to include the trait or extend the ``MockeryTestCase``.
|
|
|
103 |
|
|
|
104 |
If we are using PHPUnit's XML configuration approach, we can include the
|
|
|
105 |
following to load the ``TestListener``:
|
|
|
106 |
|
|
|
107 |
.. code-block:: xml
|
|
|
108 |
|
|
|
109 |
<listeners>
|
|
|
110 |
<listener class="\Mockery\Adapter\Phpunit\TestListener"></listener>
|
|
|
111 |
</listeners>
|
|
|
112 |
|
|
|
113 |
Make sure Composer's or Mockery's autoloader is present in the bootstrap file
|
|
|
114 |
or we will need to also define a "file" attribute pointing to the file of the
|
|
|
115 |
``TestListener`` class.
|
|
|
116 |
|
|
|
117 |
If we are creating the test suite programmatically we may add the listener
|
|
|
118 |
like this:
|
|
|
119 |
|
|
|
120 |
.. code-block:: php
|
|
|
121 |
|
|
|
122 |
// Create the suite.
|
|
|
123 |
$suite = new PHPUnit\Framework\TestSuite();
|
|
|
124 |
|
|
|
125 |
// Create the listener and add it to the suite.
|
|
|
126 |
$result = new PHPUnit\Framework\TestResult();
|
|
|
127 |
$result->addListener(new \Mockery\Adapter\Phpunit\TestListener());
|
|
|
128 |
|
|
|
129 |
// Run the tests.
|
|
|
130 |
$suite->run($result);
|
|
|
131 |
|
|
|
132 |
.. caution::
|
|
|
133 |
|
|
|
134 |
PHPUnit provides a functionality that allows
|
|
|
135 |
`tests to run in a separated process <http://phpunit.de/manual/current/en/appendixes.annotations.html#appendixes.annotations.runTestsInSeparateProcesses>`_,
|
|
|
136 |
to ensure better isolation. Mockery verifies the mocks expectations using the
|
|
|
137 |
``Mockery::close()`` method, and provides a PHPUnit listener, that automatically
|
|
|
138 |
calls this method for us after every test.
|
|
|
139 |
|
|
|
140 |
However, this listener is not called in the right process when using
|
|
|
141 |
PHPUnit's process isolation, resulting in expectations that might not be
|
|
|
142 |
respected, but without raising any ``Mockery\Exception``. To avoid this,
|
|
|
143 |
we cannot rely on the supplied Mockery PHPUnit ``TestListener``, and we need
|
|
|
144 |
to explicitly call ``Mockery::close``. The easiest solution to include this
|
|
|
145 |
call in the ``tearDown()`` method, as explained previously.
|