Valinor/tests/Integration/Mapping/VariadicParameterMappingTest.php
Romain Canon ecafba3b21 feat!: introduce method to register constructors used during mapping
It is now mandatory to explicitly register custom constructors —
including named constructors — that can be used by the mapper. The
former automatic registration of named constructor feature doesn't
work anymore.

BREAKING CHANGE: existing code must list all named constructors that
were previously automatically used by the mapper, and registerer them
using the method `MapperBuilder::registerConstructor()`.

The method `MapperBuilder::bind()` has been deprecated, the method above
should be used instead.

```php
final class SomeClass
{
    public static function namedConstructor(string $foo): self
    {
        // …
    }
}

(new \CuyZ\Valinor\MapperBuilder())
    ->registerConstructor(
        SomeClass::namedConstructor(...),
        // …or for PHP < 8.1:
        [SomeClass::class, 'namedConstructor'],
    )
    ->mapper()
    ->map(SomeClass::class, [
        // …
    ]);
```
2022-03-24 13:03:55 +01:00

153 lines
4.3 KiB
PHP

<?php
declare(strict_types=1);
namespace CuyZ\Valinor\Tests\Integration\Mapping;
use CuyZ\Valinor\Mapper\MappingError;
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
final class VariadicParameterMappingTest extends IntegrationTest
{
public function test_only_variadic_parameters_are_mapped_properly(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(SomeClassWithOnlyVariadicParameters::class, [
'values' => ['foo', 'bar', 'baz'],
]);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame(['foo', 'bar', 'baz'], $object->values);
}
public function test_variadic_parameters_are_mapped_properly_when_string_keys_are_given(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(SomeClassWithOnlyVariadicParameters::class, [
'values' => [
'foo' => 'foo',
'bar' => 'bar',
'baz' => 'baz',
],
]);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame(['foo', 'bar', 'baz'], $object->values);
}
public function test_named_constructor_with_only_variadic_parameters_are_mapped_properly(): void
{
try {
$object = $this->mapperBuilder
// @PHP8.1 first-class callable syntax
->registerConstructor([SomeClassWithNamedConstructorWithOnlyVariadicParameters::class, 'new'])
->mapper()
->map(SomeClassWithNamedConstructorWithOnlyVariadicParameters::class, [
'values' => ['foo', 'bar', 'baz'],
]);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame(['foo', 'bar', 'baz'], $object->values);
}
public function test_non_variadic_and_variadic_parameters_are_mapped_properly(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(SomeClassWithNonVariadicAndVariadicParameters::class, [
'int' => 42,
'values' => ['foo', 'bar', 'baz'],
]);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame(42, $object->int);
self::assertSame(['foo', 'bar', 'baz'], $object->values);
}
public function test_named_constructor_with_non_variadic_and_variadic_parameters_are_mapped_properly(): void
{
try {
$object = $this->mapperBuilder
// @PHP8.1 first-class callable syntax
->registerConstructor([SomeClassWithNamedConstructorWithNonVariadicAndVariadicParameters::class, 'new'])
->mapper()
->map(SomeClassWithNamedConstructorWithNonVariadicAndVariadicParameters::class, [
'int' => 42,
'values' => ['foo', 'bar', 'baz'],
]);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame(42, $object->int);
self::assertSame(['foo', 'bar', 'baz'], $object->values);
}
}
final class SomeClassWithOnlyVariadicParameters
{
/** @var string[] */
public array $values;
public function __construct(string ...$values)
{
$this->values = $values;
}
}
final class SomeClassWithNamedConstructorWithOnlyVariadicParameters
{
/** @var string[] */
public array $values;
private function __construct(string ...$values)
{
$this->values = $values;
}
public static function new(string ...$values): self
{
return new self(...$values);
}
}
final class SomeClassWithNonVariadicAndVariadicParameters
{
public int $int;
/** @var string[] */
public array $values;
public function __construct(int $int, string ...$values)
{
$this->int = $int;
$this->values = $values;
}
}
final class SomeClassWithNamedConstructorWithNonVariadicAndVariadicParameters
{
public int $int;
/** @var string[] */
public array $values;
private function __construct(int $int, string ...$values)
{
$this->int = $int;
$this->values = $values;
}
public static function new(int $int, string ...$values): self
{
return new self($int, ...$values);
}
}