Skip to content

Commit

Permalink
Custom object formatters
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinMystikJonas committed Jan 24, 2021
1 parent 14a510d commit c5088d1
Show file tree
Hide file tree
Showing 3 changed files with 243 additions and 4 deletions.
27 changes: 23 additions & 4 deletions library/Mockery.php
Expand Up @@ -662,10 +662,25 @@ private static function objectToArray($object, $nesting = 3)
return array('...');
}

return array(
'class' => get_class($object),
'properties' => self::extractInstancePublicProperties($object, $nesting)
$class = get_class($object);
$customFormatterClass = self::getConfiguration()->findObjectFormatter($class);

$array = array(
'class' => $class,
'identity' => '#' . md5(spl_object_hash($object))
);

if ($customFormatterClass) {
$customFormatter = self::getConfiguration()->getObjectFormatter($customFormatterClass);
$array = array_merge($array, $customFormatter($object));
} else {
$array = array_merge(
$array,
array('properties' => self::extractInstancePublicProperties($object, $nesting))
);
}

return $array;
}

/**
Expand All @@ -685,7 +700,11 @@ private static function extractInstancePublicProperties($object, $nesting)
foreach ($properties as $publicProperty) {
if (!$publicProperty->isStatic()) {
$name = $publicProperty->getName();
$cleanedProperties[$name] = self::cleanupNesting($object->$name, $nesting);
try {
$cleanedProperties[$name] = self::cleanupNesting($object->$name, $nesting);
} catch (\Exception $exception) {
$cleanedProperties[$name] = $exception->getMessage();
}
}
}

Expand Down
33 changes: 33 additions & 0 deletions library/Mockery/Configuration.php
Expand Up @@ -67,6 +67,13 @@ public function __construct()
$this->_quickDefinitionsConfiguration = new QuickDefinitionsConfiguration();
}

/**
* Custom object formatters
*
* @var array
*/
protected $_objectFormatters = array();

/**
* Set boolean to allow/prevent mocking of non-existent methods
*
Expand Down Expand Up @@ -211,4 +218,30 @@ public function reflectionCacheEnabled()
{
return $this->_reflectionCacheEnabled;
}

public function setObjectFormatter($class, $formatterCallback)
{
$this->_objectFormatters[$class] = $formatterCallback;
}

public function findObjectFormatter($class)
{
$parentClass = $class;
do {
$classes[] = $parentClass;
$parentClass = get_parent_class($parentClass);
} while ($parentClass);
$classesAndInterfaces = array_merge($classes, class_implements($class));
foreach ($classesAndInterfaces as $type) {
if (isset($this->_objectFormatters[$type])) {
return $type;
}
}
return null;
}

public function getObjectFormatter($class)
{
return $this->_objectFormatters[$class];
}
}
187 changes: 187 additions & 0 deletions tests/Mockery/WithCustomFormatterExpectationTest.php
@@ -0,0 +1,187 @@
<?php
/**
* Mockery
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @subpackage UnitTests
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/

use PHPUnit\Framework\TestCase;

class WithCustomFormatterExpectationTest extends TestCase
{
public function setUp(): void
{
\Mockery::getConfiguration()->setObjectFormatter(
'ClassWithCustomFormatter',
function ($object) {
return array(
"properties" => array(
"stringProperty" => $object->stringProperty
),
"getters" => array(
"gettedProperty" => $object->getArrayProperty()
)
);
}
);
\Mockery::getConfiguration()->setObjectFormatter(
'InterfaceWithCustomFormatter',
function ($object) {
return array(
"properties" => array(
"stringProperty" => $object->stringProperty
),
"getters" => array(
"gettedProperty" => $object->getArrayProperty()
)
);
}
);
}

/**
* @dataProvider findObjectFormatterDataProvider
*/
public function testFindObjectFormatter($object, $expected)
{
$this->assertEquals(
$expected,
\Mockery::getConfiguration()->findObjectFormatter(get_class($object))
);
}

public function findObjectFormatterDataProvider()
{
return array(
array(
new \StdClass(),
null
),
array(
new ClassWithoutCustomFormatter(),
null
),
array(
new ClassWithCustomFormatter(),
'ClassWithCustomFormatter'
),
array(
new ClasschildOfWithCustomFormatter(),
'ClassWithCustomFormatter'
),
array(
new ClassImplementsWithCustomFormatter(),
'InterfaceWithCustomFormatter'
)
);
}

/**
* @dataProvider formatObjectsDataProvider
*/
public function testFormatObjects($obj, $shouldContains, $shouldNotContains)
{
$string = Mockery::formatObjects(array($obj));
foreach ($shouldContains as $containString) {
$this->assertStringContainsString($containString, $string);
}
foreach ($shouldNotContains as $containString) {
$this->assertStringNotContainsString($containString, $string);
}
}

public function formatObjectsDataProvider()
{
return array(
array(
new ClassWithoutCustomFormatter(),
array(
'stringProperty',
'numberProperty',
'arrayProperty'
),
array(
'privateProperty'
)
),
array(
new ClassWithCustomFormatter(),
array(
'stringProperty',
'gettedProperty'
),
array(
'numberProperty',
'privateProperty'
)
),
array(
new ClassImplementsWithCustomFormatter(),
array(
'stringProperty',
'gettedProperty'
),
array(
'numberProperty',
'privateProperty'
)
),
);
}
}

class ClassWithoutCustomFormatter
{
public $stringProperty = "a string";
public $numberProperty = 123;
public $arrayProperty = array('a', 'nother', 'array');
private $privateProperty = "private";
}

class ClassWithCustomFormatter
{
public $stringProperty = "a string";
public $numberProperty = 123;
private $arrayProperty = array('a', 'nother', 'array');
private $privateProperty = "private";

public function getArrayProperty()
{
return $this->arrayProperty;
}
}

class ClassChildOfWithCustomFormatter extends ClassWithCustomFormatter
{
}

interface InterfaceWithCustomFormatter
{
}

class ClassImplementsWithCustomFormatter implements InterfaceWithCustomFormatter
{
public $stringProperty = "a string";
public $numberProperty = 123;
private $privateProperty = "private";
private $arrayProperty = array('a', 'nother', 'array');

public function getArrayProperty()
{
return $this->arrayProperty;
}
}

0 comments on commit c5088d1

Please sign in to comment.