diff --git a/src/Laravel/Constraint/Bus/HasHandler.php b/src/Laravel/Constraint/Bus/HasHandler.php new file mode 100644 index 0000000..667d793 --- /dev/null +++ b/src/Laravel/Constraint/Bus/HasHandler.php @@ -0,0 +1,61 @@ +bus = Bus::getFacadeRoot(); + } + + protected function matches(mixed $other): bool + { + is_string($other) or throw new InvalidArgumentException( + self::class . ' can only be evaluated for strings, got ' . gettype($other) . '.', + ); + class_exists($other) or throw new InvalidArgumentException( + self::class . " can only be evaluated for existing classes, got $other.", + ); + $message = new ReflectionClass($other)->newInstanceWithoutConstructor(); + $actualHandler = $this->bus->getCommandHandler($message); + + if ($actualHandler === false) { + $this->additionalFailureDescriptions[] = "$other has no handler mapped to it."; + + return false; + } + + if ($actualHandler::class !== $this->handlerClassFQN) { + $this->additionalFailureDescriptions[] = "$other has a different handler mapped to it."; + + return false; + } + + return true; + } + + public function toString(): string + { + return 'has handler'; + } +} diff --git a/src/Laravel/Constraint/Bus/HasHandlerTest.php b/src/Laravel/Constraint/Bus/HasHandlerTest.php new file mode 100644 index 0000000..91b0a74 --- /dev/null +++ b/src/Laravel/Constraint/Bus/HasHandlerTest.php @@ -0,0 +1,77 @@ +expectException(InvalidArgumentException::class); + $this->expectExceptionMessage(HasHandler::class . ' can only be evaluated for strings'); + + $this->assertThat($value, new HasHandler('SomeHandlerClassFCN')); + } + + #[Test] + public function itCannotEvaluateStringThatAreNotExistingClasses(): void + { + $value = 'NotAClass'; + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage(HasHandler::class . " can only be evaluated for existing classes, got $value."); + + $this->assertThat($value, new HasHandler('SomeHandlerClassFCN')); + } + + #[Test] + public function itFailsWhenNoHandlerIsMapped(): void + { + $messageClassFCN = stdClass::class; + + $this->expectException(ExpectationFailedException::class); + $this->expectExceptionMessage('has handler'); + $this->expectExceptionMessage('stdClass has no handler mapped to it'); + + $this->assertThat($messageClassFCN, new HasHandler('SomeHandlerClassFCN')); + } + + #[Test] + public function itFailsWhenDifferentHandlerIsMapped(): void + { + $messageClassFCN = stdClass::class; + Bus::map([$messageClassFCN => SpyCallable::class]); + + $this->expectException(ExpectationFailedException::class); + $this->expectExceptionMessage('has handler'); + $this->expectExceptionMessage('stdClass has a different handler mapped to it'); + + $this->assertThat($messageClassFCN, new HasHandler('SomeHandlerClassFCN')); + } + + #[Test] + public function itPassesWhenGivenHandlerIsMapped(): void + { + $messageClassFCN = stdClass::class; + Bus::map([$messageClassFCN => SpyCallable::class]); + + $this->assertThat($messageClassFCN, new HasHandler(SpyCallable::class)); + } +}