Qafoo GmbH - passion for software quality
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:Author: Benjamin Eberlei
:Date: Wed, 13 Mar 2013 09:24:48 +0100
:Revision: 11
:Copyright: All rights reserved
==================
Mocking with Phake
==================
:Keywords:
testing, php, automation, quality assurance, phpunit, mock, spy, stub,
phake, library
:Description:
The use of Mock and Stub Objects is an important skill to learn when using
Test Driven Development (TDD). Mock objects allow you to replace
dependencies of an object with lookalikes, much like crash test dummies are
used during automobile safety tests so humans aren't harmed.
:Abstract:
The use of Mock and Stub Objects is an important skill to learn when using
Test Driven Development (TDD). Mock objects allow you to replace
dependencies of an object with lookalikes, much like crash test dummies are
used during automobile safety tests so humans aren't harmed.
Update (14.3.2013): Introduced Test Double wording instead of using mock objects
for everything to more cleanly describe the different concepts.
The use of Test Doubles is an important skill to learn when
using Test Driven Development (TDD). Test Doubles allow you to replace
dependencies of an object with lookalikes, much like crash test
dummies are used during automobile safety tests so humans aren't harmed.
.. note::
Get a Qafoo expert on-site to `get your team started with testing and mock
Objects`__.
__ /services/training/topics/automated_testing_php.html
Test Doubles Explained
----------------------
Creating a test double in PHP involves creating a new class that extends the
public API of the original class with empty methods. You can safely use all
methods of a test double and they will do nothing, rather than calling the
original code of the original class. There are two ways to create these test
doubles: You can write them yourself or use one of the many existing
libraries.
I would strongly recommend to use any of the existing libraries that can
simplify and automate this task for you. Technically they work using
code-generation at run-time.
To allow interactions with test doubles there are three ways to configure them
in any library:
- Add expectations of the arguments passed to a method (Verification)
- Add results that are returned from a method-call to the mock object (Stubbing)
- Delegate calls to the original code (Spying)
Test doubles using the first approach are called Mock Objects.
Objects of the second type are called Stubs, of the third type Spies.
Benefits of Test Doubles
------------------------
There are many reasons why test doubles are useful:
- Allow units (objects) to be tested in isolation of their dependencies.
This is done by replacing the dependencies with test doubles.
- Allow verification of behavior between objects. In contrast
to assertions that can only verify the state of objects in isolation.
This makes them very useful with relation to Behavior Driven Development (BDD)
inside your unit-tests.
- Test Doubles are useful to test-drive new interfaces based on required behavior
without caring for the implementation at the moment.
That means testdoubles are invaluable to move from state-based object-oriented
programming to a behavioral approach based on sending messages between objects.
Introduction to Phake
---------------------
Using Test Doubles in PHPUnit tests means using the built-in `MockObjects library
`_ for
quite some years. In the last years two contenders emerged that can be used
as optional dependencies in PHPUnit:
- `Mockery by Padraic Brady `_
- `Phake by Mike Lively `_
Both can be installed using Composer and integrated into your projects
very easily.
This blog post introduces Phake, because it works quite
differently than both PHPUnit Mock Objects and Mockery:
1. In the well known `four phase test
`_ with Setup, Exercise,
Verify, Teardown both PHPUnit mocks and Mockery require expectations to be part
of the "setup" phase.
This is unfortunate, because mock expectations are much more related to the "Verify"
phase instead. This happens in PHPUnit and Mockery, because they don't
explicitly differentiate between methods that are mocked (verification) or
stubbed (returning results). Phake introduces a differentiation by
requiring different APIs to be used for configuration.
2. Instead of using strings for method names and builder methods for arguments,
Phake let's you prototype the method-call in actual PHP code. This simplifies
the mock object configuration considerably and requires much less typing.
Let's see an example containing both mock and stub objects in one
test for loading the weather data for a given location.
::
getWeatherForLocation()->thenReturn(
new Struct\Weather( 'Fair', 23, 0, 'NW' )
);
$loader = new Loader($functional, $logger);
// 2. exercise
$locatedWeather = $loader->getWeatherForLocation(
new Struct\Location( 'Berlin', 'Germany' )
);
// 3. verify
$this->assertInstanceOf(
'Qafoo\\Weather\\Struct\\LocatedWeather',
$locatedWeather
);
// Verification with Phake::verify()
\Phake::verify($logger)->log('Fetched weather for Berlin Germany.');
}
}
Using the ``Phake::when()`` call and passing a mock object you can prototype
what a method call should return for your code to show a desired behavior.
See how we can just call ``->getWeatherForLocation()`` as a prototype for
how the stub behaves instead of PHPUnits ``->method('getWeatherForLocation')`` or Mockerys
``->shouldRecieve('getWeatherForLocation')``.
Using ``thenReturn`` specifies the return value of this method call
and completes the description of how the stub works. If you want to return
different values on consecutive calls, just chain multiple ``thenReturn``
calls. You can use ``thenThrow`` to throw exceptions.
Verification is done with ``Phake::verify()`` after the tested code
was actually exercised. We again prototype what method calls and
which arguments we want to verify, in this case ``->log('Fetched weather for
Berlin Germany');`` on the logger mock.
This is a very simple stubbing and verification example with Phake.
Comparable to PHPUnit and Mockery, we could add more complex
expectations:
- Using argument matchers to verify the structure of arguments used in method calls.
- Checking multiple invocations such as exactly n-times, at least N-times or others.
- Verify no interaction with a mock happened at all.
- Verify no further interaction happened than the ones already verified.
Conclusion
----------
Phake is a great mocking library and can be easily integrated into PHPUnit.
Its new approach to prototype mocks and stubs and the separation between
stubbing and verification phases is very refreshing and easy to use.
If you want to go into more detail and learn about Phake, you should check
out the `extensive documentation
`_.
..
Local Variables:
mode: rst
fill-column: 79
End:
vim: et syn=rst tw=79
Trackbacks
==========
Comments
========