test(router): verify custom exceptions reach exception callback

This commit is contained in:
kj
2026-09-07 17:34:14 -03:00
parent 9ddb00e719
commit 86ab8b979a

View File

@@ -4,6 +4,7 @@ namespace Tests\Unit;
use Exception;
use Libs\Neuron;
use Libs\Request;
use Libs\Router;
use LogicException;
use PDOException;
@@ -25,10 +26,14 @@ use TypeError;
final class RouterTest extends TestCase
{
private array $serverBackup = [];
private array $getBackup = [];
private array $postBackup = [];
protected function setUp(): void
{
$this->serverBackup = $_SERVER;
$this->getBackup = $_GET;
$this->postBackup = $_POST;
$_SERVER['REQUEST_METHOD'] = 'GET';
unset($_SERVER['HTTP_ACCEPT']);
http_response_code(200);
@@ -38,6 +43,8 @@ final class RouterTest extends TestCase
protected function tearDown(): void
{
$_SERVER = $this->serverBackup;
$_GET = $this->getBackup;
$_POST = $this->postBackup;
http_response_code(200);
$this->resetRouterState();
}
@@ -206,4 +213,56 @@ final class RouterTest extends TestCase
$this->assertSame('{"status":"ok"}', $output);
$this->assertSame(200, http_response_code());
}
#[Test]
public function customOnInvalidExceptionReachesTheExceptionCallbackThroughTheBoundary(): void
{
$_SERVER['REQUEST_METHOD'] = 'POST';
$_SERVER['REQUEST_URI'] = '/signup';
$_SERVER['DOCUMENT_ROOT'] = '/nonexistent-docroot';
$_POST = ['age' => '5'];
$caught = [];
Router::$exceptionCallback = function (\Throwable $exception) use (&$caught): void {
$caught[] = $exception;
};
$finalRan = false;
Router::post('/signup', function (StrictSignup $request) use (&$finalRan): void {
$finalRan = true;
});
Router::apply('/signup');
// The Request was built by the container for the final callback and its
// custom onInvalid() threw during dependency resolution: the custom type
// must arrive intact to the callback, and the final callback must not run.
$this->assertCount(1, $caught);
$this->assertInstanceOf(RequestRejected::class, $caught[0]);
$this->assertSame('The age must be at least 18.', $caught[0]->getMessage());
$this->assertSame(400, $caught[0]->getCode(), 'The status channel must survive custom exception types');
$this->assertFalse($finalRan, 'A Request that throws during DI resolution must stop the route');
}
}
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
/**
* Fixtures locales de la prueba de simetría: un tipo de excepcion propio que
* un Request hijo lanza desde su onInvalid() reescrito.
*/
final class RequestRejected extends Exception
{
}
final class StrictSignup extends Request
{
public function rules(): array
{
return ['age' => 'required|min:18'];
}
public function onInvalid(string $error): never
{
throw new RequestRejected($error, 400);
}
}