Created
October 8, 2019 11:46
-
-
Save nesk/3f324b1288f6472e8347bb3f207ca463 to your computer and use it in GitHub Desktop.
How to mock an exception
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 | |
use Symfony\Component\Security\Core\Exception\AccessDeniedException; | |
use Symfony\Component\Security\Http\Firewall\AccessListener; | |
class ThrowerChecker | |
{ | |
public function isThrownByFirewall(AccessDeniedException $exception): bool | |
{ | |
// Walking through the stack frames and returning true if one of them is triggered by a specific class | |
foreach ($exception->getTrace() as $stackItem) { | |
$class = $stackItem['class'] ?? null; | |
if ($class === AccessListener::class) { | |
return true; | |
} | |
} | |
return false; | |
} | |
} |
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 | |
use PHPUnit\Framework\TestCase; | |
use Symfony\Component\Security\Core\Exception\AccessDeniedException; | |
use Symfony\Component\Security\Http\Firewall\AccessListener; | |
class ThrowerCheckerTest extends TestCase | |
{ | |
public function testIfExceptionsThrownByFirewallAreDetected(): void | |
{ | |
$exception = new AccessDeniedException; | |
self::overrideExceptionTrace( | |
$exception, | |
[['class' => 'foo'], | |
['class' => AccessListener::class], ['class' => 'bar']] | |
); | |
} | |
/** | |
* Overrides an exception trace through reflection, since this cannot be done through mocking (getTrace is final). | |
* | |
* @param array<int, array<string, mixed>> $trace | |
*/ | |
private static function overrideExceptionTrace(\Exception $exception, array $trace): void | |
{ | |
$exceptionReflection = new \ReflectionObject($exception); | |
// Find the parent root to be able to read the "trace" property because it's defined on the \Exception class | |
while ($exceptionReflection->getParentClass() !== false) { | |
$exceptionReflection = $exceptionReflection->getParentClass(); | |
} | |
$traceReflection = $exceptionReflection->getProperty('trace'); | |
$traceReflection->setAccessible(true); | |
$traceReflection->setValue($exception, $trace); | |
$traceReflection->setAccessible(false); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment