Skip to content

Commit 8dc4edc

Browse files
authored
addition: Bus\HasHandler Laravel constraint (#22)
* Add Bus\HasHandler Laravel constraint * Ignore HasHandlerTest from code coverage
1 parent f20ac47 commit 8dc4edc

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Craftzing\TestBench\Laravel\Constraint\Bus;
6+
7+
use Craftzing\TestBench\PHPUnit\Constraint\ProvidesAdditionalFailureDescription;
8+
use Illuminate\Contracts\Bus\Dispatcher;
9+
use Illuminate\Support\Facades\Bus;
10+
use InvalidArgumentException;
11+
use PHPUnit\Framework\Constraint\Constraint;
12+
use ReflectionClass;
13+
14+
use function class_exists;
15+
use function gettype;
16+
use function is_string;
17+
18+
final class HasHandler extends Constraint
19+
{
20+
use ProvidesAdditionalFailureDescription;
21+
22+
private readonly Dispatcher $bus;
23+
24+
public function __construct(
25+
/* @var class-string */
26+
private readonly string $handlerClassFQN,
27+
) {
28+
$this->bus = Bus::getFacadeRoot();
29+
}
30+
31+
protected function matches(mixed $other): bool
32+
{
33+
is_string($other) or throw new InvalidArgumentException(
34+
self::class . ' can only be evaluated for strings, got ' . gettype($other) . '.',
35+
);
36+
class_exists($other) or throw new InvalidArgumentException(
37+
self::class . " can only be evaluated for existing classes, got $other.",
38+
);
39+
$message = new ReflectionClass($other)->newInstanceWithoutConstructor();
40+
$actualHandler = $this->bus->getCommandHandler($message);
41+
42+
if ($actualHandler === false) {
43+
$this->additionalFailureDescriptions[] = "$other has no handler mapped to it.";
44+
45+
return false;
46+
}
47+
48+
if ($actualHandler::class !== $this->handlerClassFQN) {
49+
$this->additionalFailureDescriptions[] = "$other has a different handler mapped to it.";
50+
51+
return false;
52+
}
53+
54+
return true;
55+
}
56+
57+
public function toString(): string
58+
{
59+
return 'has handler';
60+
}
61+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Craftzing\TestBench\Laravel\Constraint\Bus;
6+
7+
use Craftzing\TestBench\PHPUnit\Doubles\SpyCallable;
8+
use Illuminate\Support\Facades\Bus;
9+
use InvalidArgumentException;
10+
use Orchestra\Testbench\TestCase;
11+
use PHPUnit\Framework\Attributes\Test;
12+
use PHPUnit\Framework\Attributes\TestWith;
13+
use PHPUnit\Framework\ExpectationFailedException;
14+
use stdClass;
15+
16+
/**
17+
* @codeCoverageIgnore
18+
*/
19+
final class HasHandlerTest extends TestCase
20+
{
21+
#[Test]
22+
#[TestWith([true], 'Boolean')]
23+
#[TestWith([1], 'Integers')]
24+
#[TestWith([['event']], 'Array')]
25+
public function itCannotEvaluateUnsupportedValueTypes(mixed $value): void
26+
{
27+
$this->expectException(InvalidArgumentException::class);
28+
$this->expectExceptionMessage(HasHandler::class . ' can only be evaluated for strings');
29+
30+
$this->assertThat($value, new HasHandler('SomeHandlerClassFCN'));
31+
}
32+
33+
#[Test]
34+
public function itCannotEvaluateStringThatAreNotExistingClasses(): void
35+
{
36+
$value = 'NotAClass';
37+
38+
$this->expectException(InvalidArgumentException::class);
39+
$this->expectExceptionMessage(HasHandler::class . " can only be evaluated for existing classes, got $value.");
40+
41+
$this->assertThat($value, new HasHandler('SomeHandlerClassFCN'));
42+
}
43+
44+
#[Test]
45+
public function itFailsWhenNoHandlerIsMapped(): void
46+
{
47+
$messageClassFCN = stdClass::class;
48+
49+
$this->expectException(ExpectationFailedException::class);
50+
$this->expectExceptionMessage('has handler');
51+
$this->expectExceptionMessage('stdClass has no handler mapped to it');
52+
53+
$this->assertThat($messageClassFCN, new HasHandler('SomeHandlerClassFCN'));
54+
}
55+
56+
#[Test]
57+
public function itFailsWhenDifferentHandlerIsMapped(): void
58+
{
59+
$messageClassFCN = stdClass::class;
60+
Bus::map([$messageClassFCN => SpyCallable::class]);
61+
62+
$this->expectException(ExpectationFailedException::class);
63+
$this->expectExceptionMessage('has handler');
64+
$this->expectExceptionMessage('stdClass has a different handler mapped to it');
65+
66+
$this->assertThat($messageClassFCN, new HasHandler('SomeHandlerClassFCN'));
67+
}
68+
69+
#[Test]
70+
public function itPassesWhenGivenHandlerIsMapped(): void
71+
{
72+
$messageClassFCN = stdClass::class;
73+
Bus::map([$messageClassFCN => SpyCallable::class]);
74+
75+
$this->assertThat($messageClassFCN, new HasHandler(SpyCallable::class));
76+
}
77+
}

0 commit comments

Comments
 (0)