minor #37346 Added Unit tests for php 8 union types (derrabus)

This PR was merged into the 3.4 branch.

Discussion
----------

Added Unit tests for php 8 union types

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | N/A
| License       | MIT
| Doc PR        | N/A

The missing test cases for #37340.

Commits
-------

2ca8ecdb74 Added Unit tests for php 8 union types.
This commit is contained in:
Nicolas Grekas 2020-06-18 22:40:01 +02:00
commit e707967ea8
6 changed files with 147 additions and 2 deletions

View File

@ -254,6 +254,25 @@ class AutowirePassTest extends TestCase
$pass->process($container);
}
/**
* @requires PHP 8
*/
public function testTypeNotGuessableUnionType()
{
$this->expectException('Symfony\Component\DependencyInjection\Exception\AutowiringFailedException');
$this->expectExceptionMessage('Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\UnionClasses::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionA|Symfony\Component\DependencyInjection\Tests\Compiler\CollisionB" but this class was not found.');
$container = new ContainerBuilder();
$container->register(CollisionA::class);
$container->register(CollisionB::class);
$aDefinition = $container->register('a', UnionClasses::class);
$aDefinition->setAutowired(true);
$pass = new AutowirePass();
$pass->process($container);
}
public function testTypeNotGuessableWithTypeSet()
{
$container = new ContainerBuilder();
@ -350,6 +369,40 @@ class AutowirePassTest extends TestCase
$this->assertEquals(Foo::class, $definition->getArgument(2));
}
/**
* @requires PHP 8
*/
public function testParameterWithNullUnionIsSkipped()
{
$container = new ContainerBuilder();
$optDefinition = $container->register('opt', UnionNull::class);
$optDefinition->setAutowired(true);
(new AutowirePass())->process($container);
$definition = $container->getDefinition('opt');
$this->assertNull($definition->getArgument(0));
}
/**
* @requires PHP 8
*/
public function testParameterWithNullUnionIsAutowired()
{
$container = new ContainerBuilder();
$container->register(CollisionInterface::class, CollisionA::class);
$optDefinition = $container->register('opt', UnionNull::class);
$optDefinition->setAutowired(true);
(new AutowirePass())->process($container);
$definition = $container->getDefinition('opt');
$this->assertEquals(CollisionInterface::class, $definition->getArgument(0));
}
public function testDontTriggerAutowiring()
{
$container = new ContainerBuilder();
@ -459,6 +512,21 @@ class AutowirePassTest extends TestCase
(new AutowirePass())->process($container);
}
/**
* @requires PHP 8
*/
public function testUnionScalarArgsCannotBeAutowired()
{
$this->expectException('Symfony\Component\DependencyInjection\Exception\AutowiringFailedException');
$this->expectExceptionMessage('Cannot autowire service "union_scalars": argument "$timeout" of method "Symfony\Component\DependencyInjection\Tests\Compiler\UnionScalars::__construct()" is type-hinted "int|float", you should configure its value explicitly.');
$container = new ContainerBuilder();
$container->register('union_scalars', UnionScalars::class)
->setAutowired(true);
(new AutowirePass())->process($container);
}
public function testNoTypeArgsCannotBeAutowired()
{
$this->expectException('Symfony\Component\DependencyInjection\Exception\AutowiringFailedException');

View File

@ -2,6 +2,10 @@
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
if (PHP_VERSION_ID >= 80000) {
require __DIR__.'/uniontype_classes.php';
}
class Foo
{
}

View File

@ -0,0 +1,24 @@
<?php
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
class UnionScalars
{
public function __construct(int|float $timeout)
{
}
}
class UnionClasses
{
public function __construct(CollisionA|CollisionB $collision)
{
}
}
class UnionNull
{
public function __construct(CollisionInterface|null $c)
{
}
}

View File

@ -243,12 +243,15 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
foreach ($reflectionType instanceof \ReflectionUnionType ? $reflectionType->getTypes() : [$reflectionType] as $type) {
$phpTypeOrClass = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : (string) $type;
if ('null' === $phpTypeOrClass) {
continue;
}
if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) {
$types[] = new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true);
} elseif ('void' === $phpTypeOrClass || 'null' === $phpTypeOrClass) {
} elseif ('void' === $phpTypeOrClass) {
$types[] = new Type(Type::BUILTIN_TYPE_NULL, $nullable);
} elseif ($reflectionType->isBuiltin()) {
} elseif ($type->isBuiltin()) {
$types[] = new Type($phpTypeOrClass, $nullable);
} else {
$types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $reflectionMethod));

View File

@ -204,6 +204,26 @@ class ReflectionExtractorTest extends TestCase
];
}
/**
* @dataProvider php80TypesProvider
* @requires PHP 8
*/
public function testExtractPhp80Type($property, array $type = null)
{
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php80Dummy', $property, []));
}
public function php80TypesProvider()
{
return [
['foo', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)]],
['bar', [new Type(Type::BUILTIN_TYPE_INT, true)]],
['timeout', [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_FLOAT)]],
['optional', [new Type(Type::BUILTIN_TYPE_INT, true), new Type(Type::BUILTIN_TYPE_FLOAT, true)]],
['string', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Stringable'), new Type(Type::BUILTIN_TYPE_STRING)]],
];
}
/**
* @dataProvider getReadableProperties
*/

View File

@ -0,0 +1,26 @@
<?php
namespace Symfony\Component\PropertyInfo\Tests\Fixtures;
class Php80Dummy
{
public function getFoo(): array|null
{
}
public function setBar(int|null $bar)
{
}
public function setTimeout(int|float $timeout)
{
}
public function getOptional(): int|float|null
{
}
public function setString(string|\Stringable $string)
{
}
}