From 273fd275fbbbcb5c9fdddde819fb70bc788b443e Mon Sep 17 00:00:00 2001 From: martinjonas Date: Sun, 9 Jul 2017 13:15:02 +0200 Subject: [PATCH] Custom object formatters Custom object formatters - code style fix Custom object formatters - code style fix 2 --- library/Mockery.php | 27 ++- library/Mockery/Configuration.php | 30 +++ .../WithCustomFormatterExpectationTest.php | 187 ++++++++++++++++++ 3 files changed, 240 insertions(+), 4 deletions(-) create mode 100644 tests/Mockery/WithCustomFormatterExpectationTest.php diff --git a/library/Mockery.php b/library/Mockery.php index 3d3011ca6..c5e29d4f2 100644 --- a/library/Mockery.php +++ b/library/Mockery.php @@ -583,10 +583,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; } /** @@ -606,7 +621,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(); + } } } diff --git a/library/Mockery/Configuration.php b/library/Mockery/Configuration.php index 2f050f25b..f16f9bab8 100644 --- a/library/Mockery/Configuration.php +++ b/library/Mockery/Configuration.php @@ -47,6 +47,13 @@ class Configuration */ protected $_internalClassParamMap = array(); + /** + * Custom object formatters + * + * @var array + */ + protected $_objectFormatters = array(); + /** * Set boolean to allow/prevent mocking of non-existent methods * @@ -127,4 +134,27 @@ public function getInternalClassMethodParamMaps() { return $this->_internalClassParamMap; } + + public function setObjectFormatter($class, $formatterCallback) + { + $this->_objectFormatters[$class] = $formatterCallback; + } + + public function findObjectFormatter($class) + { + $parentClass = $class; + for ($classes[] = $parentClass; $parentClass = get_parent_class($parentClass); $classes[] = $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]; + } } diff --git a/tests/Mockery/WithCustomFormatterExpectationTest.php b/tests/Mockery/WithCustomFormatterExpectationTest.php new file mode 100644 index 000000000..2b144385d --- /dev/null +++ b/tests/Mockery/WithCustomFormatterExpectationTest.php @@ -0,0 +1,187 @@ +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->assertContains($containString, $string); + } + foreach ($shouldNotContains as $containString) { + $this->assertNotContains($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; + } +}