Occasionally you may run into code that utilizes reference parameters to provide additional output
from a method. This is not an uncommon thing to run into with legacy code. Phake provides a custom
parameter matcher (these are discussed further in Chapter 4, Method Parameter Matchers)
that allows you to set reference parameters. It can be accessed using Phake::setReference().
The only parameter to this matcher is the value you would like to set the reference parameter
to provided all other parameters match. In Example 3.9, “Stubbing a Reference Parameter” you can see an example of how
Phake::setReference() can be used.
Example 3.9. Stubbing a Reference Parameter
<?php interface IValidator { /** * @parm array $data Data to validate * @parm array &$errors contains all validation errors if the data is not valid * @return boolean True when the data is valid */ public function validate(array $data, array &$errors); } class ValidationLogger implements IValidator { private $validator; private $log; public function __construct(IValidator $validator, Logger $log) { $this->validator = $validator; $this->log = $log; } public function validate(array $data, array &$errors) { if (!$this->validator->validate($data, $errors)) { foreach ($errors as $error) { $this->log->info("Validation Error: {$error}"); } return FALSE; } return TRUE; } } class ValidationLoggerTest extends PHPUnit_Framework_TestCase { public function testValidate() { //Mock the dependencies $validator = Phake::mock('IValidator'); $log = Phake::mock('Logger'); $data = array('data1' => 'value'); $expectedErrors = array('data1 is not valid'); //Setup the stubs (Notice the Phake::setReference() Phake::when($validator)->validate($data, Phake::setReference($expectedErrors))->thenReturn(FALSE); //Instantiate the SUT $validationLogger = new ValidationLogger($validator, $log); //verify the validation is false and the message is logged $errors = array(); $this->assertFalse($validationLogger->validate($data, $errors)); Phake::verify($log)->info('Validation Error: data1 is not valid'); } } ?>
In Example 3.9, “Stubbing a Reference Parameter” I am testing a new class I have created called ValidationLogger.
It is a decorator for other implementations of IValidator that allows adding
logging to any other validator. The IValidator::validate() method will always
return an array of errors into the second parameter (a reference parameter) provided to the method.
These errors are what my logger is responsible for logging. So in order for my test to work properly,
I will need to be able to set that second parameter as a part of my stubbing call.
In the call to Phake::when($validator)->validate() I have passed a call to
Phake::setReference() as the second parameter. This is causing the mock
implementation of IValidator to set $errors in
ValidationLogger::validate() to the array specified by $expectedErrors.
This allows me to quickly and easily validate that I am actually logging the errors returned back
in the reference parameter.
By default Phake::setReference() will always return true regardless of the
parameter initially passed in. If you would like to only set a reference parameter when that reference
parameter was passed in as a certain value you can use the when() modifier.
This takes a single parameter matcher as an argument. In Example 3.10, “Stubbing a Reference Paramter”
you will see that the test has been modified to call when() on the result
of Phake::setReference(). This modification will cause the reference parameter
to be set only if the $errors parameter passed to IValidatore::validate()
is initially passed as an empty array.
Example 3.10. Stubbing a Reference Paramter
<?php class ValidationLoggerTest extends PHPUnit_Framework_TestCase { public function testValidate() { //Mock the dependencies $validator = Phake::mock('IValidator'); $log = Phake::mock('Logger'); $data = array('data1' => 'value'); $expectedErrors = array('data1 is not valid'); //Setup the stubs (Notice the Phake::setReference() Phake::when($validator)->validate($data, Phake::setReference($expectedErrors)->when(array())->thenReturn(FALSE); //Instantiate the SUT $validationLogger = new ValidationLogger($validator, $log); //verify the validation is false and the message is logged $errors = array(); $this->assertFalse($validationLogger->validate($data, $errors)); Phake::verify($log)->info('Validation Error: data1 is not valid'); } } ?>
Please note, when you are using Phake::setReference() you still must provide
an answer for the stub. If you use this function and your reference parameter is never changed,
that is generally the most common reason.