Skip to content

Commit e3a2330

Browse files
committed
improve no more middleware exception
1 parent 85cb452 commit e3a2330

4 files changed

Lines changed: 79 additions & 6 deletions

File tree

src/Middleware/NoMoreMiddleware.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,29 @@
77
use Patchlevel\Hydrator\HydratorException;
88
use RuntimeException;
99

10+
use function array_map;
11+
use function count;
12+
use function implode;
13+
use function sprintf;
14+
1015
/** @experimental */
1116
final class NoMoreMiddleware extends RuntimeException implements HydratorException
1217
{
13-
public function __construct()
18+
/** @param list<Middleware> $middlewares */
19+
public function __construct(array $middlewares)
1420
{
15-
parent::__construct('no more middlewares');
21+
if ($middlewares === []) {
22+
parent::__construct('No middleware available.');
23+
24+
return;
25+
}
26+
27+
parent::__construct(
28+
sprintf(
29+
'The next middleware in %s was requested, but no further middleware exists. The following middlewares were executed: %s',
30+
$middlewares[count($middlewares) - 1]::class,
31+
implode(', ', array_map(static fn (Middleware $middleware): string => $middleware::class, $middlewares)),
32+
),
33+
);
1634
}
1735
}

src/Middleware/Stack.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function next(): Middleware
2020
$next = $this->middlewares[$this->index] ?? null;
2121

2222
if ($next === null) {
23-
throw new NoMoreMiddleware();
23+
throw new NoMoreMiddleware($this->middlewares);
2424
}
2525

2626
$this->index++;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\Hydrator\Tests\Unit\Fixture;
6+
7+
use Patchlevel\Hydrator\Metadata\ClassMetadata;
8+
use Patchlevel\Hydrator\Middleware\Middleware;
9+
use Patchlevel\Hydrator\Middleware\Stack;
10+
11+
final class DummyMiddleware implements Middleware
12+
{
13+
/**
14+
* @param ClassMetadata<T> $metadata
15+
* @param array<string, mixed> $data
16+
* @param array<string, mixed> $context
17+
*
18+
* @return T
19+
*
20+
* @template T of object
21+
*/
22+
public function hydrate(ClassMetadata $metadata, array $data, array $context, Stack $stack): object
23+
{
24+
return $stack->next()->hydrate($metadata, $data, $context, $stack);
25+
}
26+
27+
/**
28+
* @param array<string, mixed> $context
29+
*
30+
* @return array<string, mixed>
31+
*/
32+
public function extract(ClassMetadata $metadata, object $object, array $context, Stack $stack): array
33+
{
34+
return $stack->next()->extract($metadata, $object, $context, $stack);
35+
}
36+
}

tests/Unit/Middleware/StackTest.php

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
namespace Patchlevel\Hydrator\Tests\Unit\Middleware;
66

7-
use Patchlevel\Hydrator\Middleware\Middleware;
87
use Patchlevel\Hydrator\Middleware\NoMoreMiddleware;
98
use Patchlevel\Hydrator\Middleware\Stack;
9+
use Patchlevel\Hydrator\Tests\Unit\Fixture\DummyMiddleware;
1010
use PHPUnit\Framework\Attributes\CoversClass;
1111
use PHPUnit\Framework\TestCase;
1212

@@ -16,19 +16,38 @@ final class StackTest extends TestCase
1616
public function testEmptyStack(): void
1717
{
1818
$this->expectException(NoMoreMiddleware::class);
19+
$this->expectExceptionMessage('No middleware available.');
1920

2021
$stack = new Stack([]);
2122
$stack->next();
2223
}
2324

2425
public function testStack(): void
2526
{
26-
$middleware1 = $this->createStub(Middleware::class);
27-
$middleware2 = $this->createStub(Middleware::class);
27+
$middleware1 = new DummyMiddleware();
28+
$middleware2 = new DummyMiddleware();
2829

2930
$stack = new Stack([$middleware1, $middleware2]);
3031

3132
self::assertSame($middleware1, $stack->next());
3233
self::assertSame($middleware2, $stack->next());
3334
}
35+
36+
public function testStackThrowsExceptionWhenNoMoreMiddlewareIsAvailable(): void
37+
{
38+
$middleware1 = new DummyMiddleware();
39+
$middleware2 = new DummyMiddleware();
40+
41+
$stack = new Stack([$middleware1, $middleware2]);
42+
43+
$stack->next();
44+
$stack->next();
45+
46+
$this->expectException(NoMoreMiddleware::class);
47+
$this->expectExceptionMessage(
48+
'The next middleware in Patchlevel\Hydrator\Tests\Unit\Fixture\DummyMiddleware was requested, but no further middleware exists. The following middlewares were executed: Patchlevel\Hydrator\Tests\Unit\Fixture\DummyMiddleware, Patchlevel\Hydrator\Tests\Unit\Fixture\DummyMiddleware',
49+
);
50+
51+
$stack->next();
52+
}
3453
}

0 commit comments

Comments
 (0)