diff --git a/src/Mapper/Object/CallbackObjectBuilder.php b/src/Mapper/Object/CallbackObjectBuilder.php index 1105111..813032a 100644 --- a/src/Mapper/Object/CallbackObjectBuilder.php +++ b/src/Mapper/Object/CallbackObjectBuilder.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace CuyZ\Valinor\Mapper\Object; use CuyZ\Valinor\Definition\FunctionDefinition; +use CuyZ\Valinor\Mapper\Tree\Message\ThrowableMessage; +use Exception; use function array_values; @@ -42,6 +44,10 @@ final class CallbackObjectBuilder implements ObjectBuilder /** @infection-ignore-all */ $arguments = array_values($arguments); - return ($this->callback)(...$arguments); + try { + return ($this->callback)(...$arguments); + } catch (Exception $exception) { + throw ThrowableMessage::from($exception); + } } } diff --git a/tests/Integration/Mapping/ObjectBindingMappingTest.php b/tests/Integration/Mapping/ObjectBindingMappingTest.php index 0639a0e..cfedd32 100644 --- a/tests/Integration/Mapping/ObjectBindingMappingTest.php +++ b/tests/Integration/Mapping/ObjectBindingMappingTest.php @@ -8,6 +8,7 @@ use CuyZ\Valinor\Mapper\MappingError; use CuyZ\Valinor\Tests\Integration\IntegrationTest; use DateTime; use DateTimeImmutable; +use DomainException; use stdClass; use function get_class; @@ -118,6 +119,23 @@ final class ObjectBindingMappingTest extends IntegrationTest self::assertSame(42, $result->int); self::assertSame(1337.404, $result->float); } + + public function test_object_binding_throwing_exception_fails_mapping_with_message(): void + { + try { + $this->mapperBuilder + ->bind(function (): stdClass { + // @PHP8.0 use short closure + throw new DomainException('some domain exception'); + }) + ->mapper() + ->map(stdClass::class, []); + + self::fail('No mapping error when one was expected'); + } catch (MappingError $exception) { + self::assertSame('some domain exception', (string)$exception->node()->messages()[0]); + } + } } final class SimpleDateTimeValues