Instantly share code, notes, and snippets.

Embed
What would you like to do?
<?php
use \PHPUnit_Framework_TestCase as TestCase,
\PHPUnit_Framework_MockObject_MockBuilder as MockBuilder,
\PHPUnit_Framework_MockObject_MockObject as MockObject;
trait ZF2InterfaceInjectionTrait extends TestCase
{
/**
* Provides the default mocks for each of the interfaces defined in your test configuration
* @param String|Object $mock if provided a string, I will create the mock for you, if not, I will apply the mocks to the object provided.
* @param array $args
* @return Object
*/
protected function interfaceAwareMock($mock, array $args = array())
{
$config = InterfaceAwareMockBuilder::getConfig();
$instance = is_string($mock) ? $this->getMock($mock, $args) : $mock;
if (isset($config['dependencies'])) {
foreach ($config['dependencies']['interfaces'] as $interface => $invoke) {
if ($instance instanceof $interface) {
$instance->$invoke['method']($this->getMockBuilder($invoke['invokable'])->disableOriginalConstructor()->getMock());
}
}
}
return $instance;
}
/**
* Provides the default mocks for each of the interfaces defined in the test configuration
* @param String|Object $mock If this method is provided a string, it will create the mock, if not, it will apply the arguments to the provided mock.
* @param array $args
* @return Object
*/
protected function interfaceAware($mock, array $args = array())
{
$instance = is_string($mock) ? $this->getInterfaceAwareMockBuilder($mock)->setMethods($args)->disableOriginalConstructor() : $mock;
return $instance;
}
/**
* Returns a builder object to create mock objects using a fluent interface.
*
* @param string $className
* @return PHPUnit_Framework_MockObject_MockBuilder
* @since Method available since Release 3.5.0
*/
public function getInterfaceAwareMockBuilder($className)
{
return new InterfaceAwareMockBuilder(
$this, $className
);
}
/**
* Shorthand use for simple mock writing!
* example use:
* $this->testObj = $this->interfaceAware('My\Service\MyClass', array('__construct'));
* $this->mock = $this->getMockBuilder('My\Service\MyClass\OtherMock')->disableOriginalConstructor();
* $mock = $this->mock->getMock();
*
* // Interface aware mocks will support the getMockSetup as a chain
* $localTest = $this->testObj->getMockSetup(array(
* 'methodIAmOverwriting' => array(
* 'expects' => $this->once(),
* 'will' => $this->returnValue($mock)
* ),
* ));
* // Simple use case
* $this->getMockSetup($this->mock, array(
* 'save' => array(
* 'expects' => $this->exactly(1),
* 'with' => $otherMock
* ),
* ));
*
* @param PHPUnit_Framework_MockObject_MockObject $mock
* @param array $methods
*/
public function getMockSetup($mock, array $methods = array())
{
if ($mock instanceof MockBuilder) {
$mock = $mock->setMethods(array_keys($methods))->getMock();
}
foreach ($methods as $method => $definition){
$chain = $mock->expects($definition['expects'])->method($method);
unset($definition['expects']);
foreach ($definition as $key => $value){
if (is_array($value)) {
call_user_func_array(array($chain, $key), $value);
} else {
call_user_func(array($chain, $key), $value);
}
}
}
return $mock;
}
}
class InterfaceAwareMockBuilder extends MockBuilder
{
public static function getConfig()
{
return array(
'dependencies' => array(
'interfaces' => array(
'\Some\Service\ServiceAwareInterface' => array(
'setMethod' => 'setService',
'invokable' => 'Some\Service'
),
),
),
);
}
public function getMock()
{
$instance = parent::getMock();
$config = self::getConfig();
if (isset($config['dependencies'])) {
foreach ($config['dependencies']['interfaces'] as $interface => $invoke) {
if ($instance instanceof $interface) {
$mock = $this->testCase->getMockBuilder($invoke['invokable'])->disableOriginalConstructor()->getMock();
$instance->$invoke['setMethod']($mock);
}
}
}
return $instance;
}
public function getMockSetup(array $methods = array())
{
return $this->testCase->getMockSetup($this, $methods);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment