Last active
March 26, 2024 21:18
-
-
Save malarzm/e8c6141b510708e52c8535d2a13cd613 to your computer and use it in GitHub Desktop.
PHPUnit's MemoryGuard
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace Answear\DevelopmentHelpers\PHPUnit; | |
use PHPUnit\Framework\Test; | |
use PHPUnit\Framework\TestListener; | |
use PHPUnit\Framework\TestListenerDefaultImplementation; | |
class MemoryGuard implements TestListener | |
{ | |
use TestListenerDefaultImplementation; | |
private const PHPUNIT_PROPERTY_PREFIX = 'PHPUnit'; | |
/** | |
* @var callable | |
*/ | |
private $unsetter; | |
public function __construct() | |
{ | |
$this->unsetter = function ($propertyName) { | |
unset($this->$propertyName); | |
}; | |
} | |
public function endTest(Test $test, float $time): void | |
{ | |
$this->safelyFreeProperties($test); | |
} | |
private function safelyFreeProperties(Test $test): void | |
{ | |
$testReflection = new \ReflectionObject($test); | |
foreach ($this->getAllProperties($testReflection) as $property) { | |
$this->unsetter = $this->unsetter->bindTo($test, $property->getDeclaringClass()->getName()); | |
if ($this->isSafeToFreeProperty($property)) { | |
($this->unsetter)($property->getName()); | |
} | |
} | |
} | |
private function isSafeToFreeProperty(\ReflectionProperty $property): bool | |
{ | |
return !$property->isStatic() && $this->isNotPhpUnitProperty($property); | |
} | |
private function isNotPhpUnitProperty(\ReflectionProperty $property): bool | |
{ | |
return 0 !== strpos($property->getDeclaringClass()->getName(), self::PHPUNIT_PROPERTY_PREFIX); | |
} | |
/** | |
* @return \ReflectionProperty[] | |
*/ | |
private function getAllProperties(\ReflectionObject $object): array | |
{ | |
$properties = $object->getProperties(); | |
while ($object->getParentClass()) { | |
$object = $object->getParentClass(); | |
if (0 === strpos($object->getNamespaceName(), self::PHPUNIT_PROPERTY_PREFIX)) { | |
break; | |
} | |
$properties = array_merge($properties, $object->getProperties(\ReflectionProperty::IS_PRIVATE)); | |
} | |
return $properties; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment