diff --git a/fixtures/Entity/DummyWithMethods.php b/fixtures/Entity/DummyWithMethods.php
new file mode 100644
index 000000000..dff606c2f
--- /dev/null
+++ b/fixtures/Entity/DummyWithMethods.php
@@ -0,0 +1,62 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Nelmio\Alice\Entity;
+
+class DummyWithMethods
+{
+ private $foo1;
+ private $foo2;
+ private $bar1;
+ private $bar2;
+ private $baz1;
+ private $baz2;
+ private $baz3;
+
+ public function __construct(string $foo1, string $foo2)
+ {
+ $this->foo1 = $foo1;
+ $this->foo2 = $foo2;
+ }
+
+ public static function create(string $foo1, string $foo2)
+ {
+ return new self($foo1, $foo2);
+ }
+
+ public function bar(string $bar1, string $bar2)
+ {
+ $this->bar1 = $bar1;
+ $this->bar2 = $bar2;
+ }
+
+ public function methodWithVariadic(string $baz1, string $baz2, array ...$baz3)
+ {
+ $this->baz1 = $baz1;
+ $this->baz2 = $baz2;
+ $this->baz3 = $baz3;
+ }
+
+ public function methodWithDefaultValues(string $baz1 = 'value 1', string $baz2 = 'value 2', string $baz3 = 'value 3')
+ {
+ $this->baz1 = $baz1;
+ $this->baz2 = $baz2;
+ $this->baz3 = $baz3;
+ }
+
+ public function methodWithNullables(?string $bar1, ?string $bar2)
+ {
+ $this->bar1 = $bar1;
+ $this->bar2 = $bar2;
+ }
+}
diff --git a/fixtures/Parser/files/json/named_parameters.json b/fixtures/Parser/files/json/named_parameters.json
new file mode 100644
index 000000000..e77022f16
--- /dev/null
+++ b/fixtures/Parser/files/json/named_parameters.json
@@ -0,0 +1,18 @@
+{
+ "Nelmio\\Alice\\DummyWithMethods": {
+ "dummy_with_methods": {
+ "__construct": {
+ "$foo1": "foo1",
+ "$foo2": "foo2"
+ },
+ "__calls": [
+ {
+ "bar": {
+ "$bar1": "bar1",
+ "$bar2": "bar2"
+ }
+ }
+ ]
+ }
+ }
+}
diff --git a/fixtures/Parser/files/php/named_parameters.php b/fixtures/Parser/files/php/named_parameters.php
new file mode 100644
index 000000000..aa4cbe403
--- /dev/null
+++ b/fixtures/Parser/files/php/named_parameters.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+return [
+ 'Nelmio\Alice\DummyWithMethods' =>[
+ 'dummy_with_methods' =>[
+ '__construct' =>[
+ '$foo1' =>'foo1',
+ '$foo2' =>'foo2'
+ ],
+ '__calls' =>[
+ [
+ 'bar' =>[
+ '$bar1' =>'bar1',
+ '$bar2' =>'bar2'
+ ]
+ ]
+ ]
+ ]
+ ]
+];
diff --git a/fixtures/Parser/files/yaml/named_parameters.yml b/fixtures/Parser/files/yaml/named_parameters.yml
new file mode 100644
index 000000000..67b27ba1f
--- /dev/null
+++ b/fixtures/Parser/files/yaml/named_parameters.yml
@@ -0,0 +1,9 @@
+Nelmio\Alice\DummyWithMethods:
+ dummy_with_methods:
+ __construct:
+ $foo1: foo1
+ $foo2: foo2
+ __calls:
+ - bar:
+ $bar1: bar1
+ $bar2: bar2
diff --git a/src/Bridge/Symfony/Resources/config/generator/caller.xml b/src/Bridge/Symfony/Resources/config/generator/caller.xml
index cb26021fb..d1e64967f 100644
--- a/src/Bridge/Symfony/Resources/config/generator/caller.xml
+++ b/src/Bridge/Symfony/Resources/config/generator/caller.xml
@@ -20,6 +20,7 @@
class="Nelmio\Alice\Generator\Caller\SimpleCaller">
+
+
@@ -50,6 +51,7 @@
+
diff --git a/src/Bridge/Symfony/Resources/config/generator/resolver/named_arguments.xml b/src/Bridge/Symfony/Resources/config/generator/resolver/named_arguments.xml
new file mode 100644
index 000000000..cdf239d21
--- /dev/null
+++ b/src/Bridge/Symfony/Resources/config/generator/resolver/named_arguments.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Generator/Caller/Chainable/SimpleMethodCallProcessor.php b/src/Generator/Caller/Chainable/SimpleMethodCallProcessor.php
index db867d6d0..5e90bc102 100644
--- a/src/Generator/Caller/Chainable/SimpleMethodCallProcessor.php
+++ b/src/Generator/Caller/Chainable/SimpleMethodCallProcessor.php
@@ -42,7 +42,7 @@ public function process(
GenerationContext $context,
MethodCallInterface $methodCall
): ResolvedFixtureSet {
- $result = $object->getInstance()->{$methodCall->getMethod()}(...$methodCall->getArguments());
+ $result = $object->getInstance()->{$methodCall->getMethod()}(...array_values($methodCall->getArguments()));
if ($context->needsCallResult()) {
$object = $object->withInstance($result);
diff --git a/src/Generator/Caller/SimpleCaller.php b/src/Generator/Caller/SimpleCaller.php
index bf6e3ff49..f0671ff76 100644
--- a/src/Generator/Caller/SimpleCaller.php
+++ b/src/Generator/Caller/SimpleCaller.php
@@ -18,6 +18,7 @@
use Nelmio\Alice\FixtureInterface;
use Nelmio\Alice\Generator\CallerInterface;
use Nelmio\Alice\Generator\GenerationContext;
+use Nelmio\Alice\Generator\NamedArgumentsResolver;
use Nelmio\Alice\Generator\ResolvedFixtureSet;
use Nelmio\Alice\Generator\ValueResolverAwareInterface;
use Nelmio\Alice\Generator\ValueResolverInterface;
@@ -41,10 +42,20 @@ final class SimpleCaller implements CallerInterface, ValueResolverAwareInterface
*/
private $resolver;
- public function __construct(CallProcessorInterface $callProcessor, ValueResolverInterface $resolver = null)
- {
+ /**
+ * @var NamedArgumentsResolver|null
+ */
+ private $namedArgumentsResolver;
+
+ // TODO: make $namedArgumentsResolver non-nullable in 4.0. It is currently nullable only for BC purposes
+ public function __construct(
+ CallProcessorInterface $callProcessor,
+ ValueResolverInterface $resolver = null,
+ NamedArgumentsResolver $namedArgumentsResolver = null
+ ) {
$this->callProcessor = $callProcessor;
$this->resolver = $resolver;
+ $this->namedArgumentsResolver = $namedArgumentsResolver;
}
/**
@@ -52,7 +63,7 @@ public function __construct(CallProcessorInterface $callProcessor, ValueResolver
*/
public function withValueResolver(ValueResolverInterface $resolver): self
{
- return new self($this->callProcessor, $resolver);
+ return new self($this->callProcessor, $resolver, $this->namedArgumentsResolver);
}
/**
@@ -108,6 +119,10 @@ private function processArguments(
}
}
+ if (null !== $this->namedArgumentsResolver) {
+ $arguments = $this->namedArgumentsResolver->resolveArguments($arguments, $fixture->getClassName(), $methodCall->getMethod());
+ }
+
return [$methodCall->withArguments($arguments), $fixtureSet];
}
}
diff --git a/src/Generator/Instantiator/Chainable/NoCallerMethodCallInstantiator.php b/src/Generator/Instantiator/Chainable/NoCallerMethodCallInstantiator.php
index d22a8eeb1..2eb63d525 100644
--- a/src/Generator/Instantiator/Chainable/NoCallerMethodCallInstantiator.php
+++ b/src/Generator/Instantiator/Chainable/NoCallerMethodCallInstantiator.php
@@ -15,9 +15,21 @@
use Nelmio\Alice\Definition\MethodCall\NoMethodCall;
use Nelmio\Alice\FixtureInterface;
+use Nelmio\Alice\Generator\NamedArgumentsResolver;
final class NoCallerMethodCallInstantiator extends AbstractChainableInstantiator
{
+ /**
+ * @var NamedArgumentsResolver|null
+ */
+ private $namedArgumentsResolver;
+
+ // TODO: make $namedArgumentsResolver non-nullable in 4.0. It is currently nullable only for BC purposes
+ public function __construct(NamedArgumentsResolver $namedArgumentsResolver = null)
+ {
+ $this->namedArgumentsResolver = $namedArgumentsResolver;
+ }
+
/**
* @inheritDoc
*/
@@ -35,9 +47,13 @@ protected function createInstance(FixtureInterface $fixture)
{
list($class, $arguments) = [
$fixture->getClassName(),
- array_values($fixture->getSpecs()->getConstructor()->getArguments())
+ $fixture->getSpecs()->getConstructor()->getArguments()
];
- return new $class(...$arguments);
+ if (null !== $this->namedArgumentsResolver) {
+ $arguments = $this->namedArgumentsResolver->resolveArguments($arguments, $class, '__construct');
+ }
+
+ return new $class(...array_values($arguments));
}
}
diff --git a/src/Generator/Instantiator/Chainable/StaticFactoryInstantiator.php b/src/Generator/Instantiator/Chainable/StaticFactoryInstantiator.php
index 11bcbd7ab..e4bdf68eb 100644
--- a/src/Generator/Instantiator/Chainable/StaticFactoryInstantiator.php
+++ b/src/Generator/Instantiator/Chainable/StaticFactoryInstantiator.php
@@ -16,10 +16,22 @@
use Nelmio\Alice\Definition\MethodCall\NoMethodCall;
use Nelmio\Alice\Definition\ServiceReference\StaticReference;
use Nelmio\Alice\FixtureInterface;
+use Nelmio\Alice\Generator\NamedArgumentsResolver;
use Nelmio\Alice\Throwable\Exception\Generator\Instantiator\InstantiationExceptionFactory;
final class StaticFactoryInstantiator extends AbstractChainableInstantiator
{
+ /**
+ * @var NamedArgumentsResolver|null
+ */
+ private $namedArgumentsResolver;
+
+ // TODO: make $namedArgumentsResolver non-nullable in 4.0. It is currently nullable only for BC purposes
+ public function __construct(NamedArgumentsResolver $namedArgumentsResolver = null)
+ {
+ $this->namedArgumentsResolver = $namedArgumentsResolver;
+ }
+
/**
* @inheritDoc
*/
@@ -47,6 +59,10 @@ protected function createInstance(FixtureInterface $fixture)
$arguments = [];
}
+ if (null !== $this->namedArgumentsResolver) {
+ $arguments = $this->namedArgumentsResolver->resolveArguments($arguments, $factory, $method);
+ }
+
$instance = $factory::$method(...array_values($arguments));
if (false === $instance instanceof $class) {
throw InstantiationExceptionFactory::createForInvalidInstanceType($fixture, $instance);
diff --git a/src/Generator/NamedArgumentsResolver.php b/src/Generator/NamedArgumentsResolver.php
new file mode 100644
index 000000000..0fc387d62
--- /dev/null
+++ b/src/Generator/NamedArgumentsResolver.php
@@ -0,0 +1,85 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Nelmio\Alice\Generator;
+
+class NamedArgumentsResolver
+{
+ public function resolveArguments(array $arguments, string $className, string $methodName): array
+ {
+ try {
+ $method = new \ReflectionMethod($className, $methodName);
+ } catch (\ReflectionException $exception) {
+ return $arguments;
+ }
+
+ $sortedArguments = [];
+ $buffer = [];
+
+ foreach ($method->getParameters() as $parameter) {
+ $name = $parameter->getName();
+
+ if ($parameter->isVariadic() && [] !== $arguments) {
+ $sortedArguments = array_merge($sortedArguments, $buffer, array_values($arguments));
+ $arguments = [];
+ $buffer = [];
+
+ break;
+ }
+
+ if (array_key_exists($name, $arguments)) {
+ $sortedArguments = array_merge($sortedArguments, $buffer, [$name => $arguments[$name]]);
+ unset($arguments[$name]);
+ $buffer = [];
+
+ continue;
+ }
+
+ foreach ($arguments as $key => $value) {
+ if (is_int($key)) {
+ $sortedArguments = array_merge($sortedArguments, $buffer, [$arguments[$key]]);
+ unset($arguments[$key]);
+ $buffer = [];
+
+ continue 2;
+ }
+ }
+
+ if (!$parameter->isDefaultValueAvailable()) {
+ throw new \RuntimeException(sprintf(
+ 'Argument $%s of %s::%s() is not passed a value and does not define a default one.',
+ $name,
+ $className,
+ $methodName
+ ));
+ }
+
+ $buffer[] = $parameter->getDefaultValue();
+ }
+
+ $unknownNamedParameters = array_filter(array_keys($arguments), static function ($key) {
+ return is_string($key);
+ });
+
+ if ([] !== $unknownNamedParameters) {
+ throw new \RuntimeException(sprintf(
+ 'Unknown arguments for %s::%s(): $%s.',
+ $className,
+ $methodName,
+ implode(', $', $unknownNamedParameters)
+ ));
+ }
+
+ return $sortedArguments;
+ }
+}
diff --git a/src/Loader/NativeLoader.php b/src/Loader/NativeLoader.php
index cf5a6fb02..7d163f8c2 100644
--- a/src/Loader/NativeLoader.php
+++ b/src/Loader/NativeLoader.php
@@ -116,6 +116,7 @@
use Nelmio\Alice\Generator\Instantiator\InstantiatorRegistry;
use Nelmio\Alice\Generator\Instantiator\InstantiatorResolver;
use Nelmio\Alice\Generator\InstantiatorInterface;
+use Nelmio\Alice\Generator\NamedArgumentsResolver;
use Nelmio\Alice\Generator\ObjectGenerator\CompleteObjectGenerator;
use Nelmio\Alice\Generator\ObjectGenerator\SimpleObjectGenerator;
use Nelmio\Alice\Generator\ObjectGeneratorInterface;
@@ -204,6 +205,7 @@
* @method PropertyAccessorInterface getPropertyAccessor()
* @method CallerInterface getCaller()
* @method CallProcessorInterface getCallProcessor()
+ * @method NamedArgumentsResolver getNamedArgumentsResolver()
*/
class NativeLoader implements FilesLoaderInterface, FileLoaderInterface, DataLoaderInterface
{
@@ -589,18 +591,25 @@ protected function createFakerGenerator(): FakerGenerator
protected function createInstantiator(): InstantiatorInterface
{
+ $namedArgumentsResolver = $this->getNamedArgumentsResolver();
+
return new ExistingInstanceInstantiator(
new InstantiatorResolver(
new InstantiatorRegistry([
- new NoCallerMethodCallInstantiator(),
+ new NoCallerMethodCallInstantiator($namedArgumentsResolver),
new NullConstructorInstantiator(),
new NoMethodCallInstantiator(),
- new StaticFactoryInstantiator(),
+ new StaticFactoryInstantiator($namedArgumentsResolver),
])
)
);
}
+ private function createNamedArgumentsResolver(): NamedArgumentsResolver
+ {
+ return new NamedArgumentsResolver();
+ }
+
protected function createHydrator(): HydratorInterface
{
return new SimpleHydrator(
@@ -626,7 +635,7 @@ protected function createPropertyAccessor(): PropertyAccessorInterface
protected function createCaller(): CallerInterface
{
- return new SimpleCaller($this->getCallProcessor(), $this->getValueResolver());
+ return new SimpleCaller($this->getCallProcessor(), $this->getValueResolver(), $this->getNamedArgumentsResolver());
}
protected function createCallProcessor(): CallProcessorInterface
diff --git a/tests/Generator/NamedArgumentsResolverTest.php b/tests/Generator/NamedArgumentsResolverTest.php
new file mode 100644
index 000000000..fd1ed4ee1
--- /dev/null
+++ b/tests/Generator/NamedArgumentsResolverTest.php
@@ -0,0 +1,330 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Nelmio\Alice\Generator;
+
+use Nelmio\Alice\Entity\DummyWithMethods;
+use Nelmio\Alice\Entity\EmptyDummy;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * @covers \Nelmio\Alice\Generator\NamedArgumentsResolver
+ */
+class NamedArgumentsResolverTest extends TestCase
+{
+ /**
+ * @dataProvider provideResolveArgumentsCases
+ */
+ public function testResolveArguments(string $className, string $methodName, array $argument, array $expectedResult)
+ {
+ $resolver = new NamedArgumentsResolver();
+
+ self::assertSame(
+ $expectedResult,
+ $resolver->resolveArguments($argument, $className, $methodName)
+ );
+ }
+
+ public function provideResolveArgumentsCases()
+ {
+ yield 'constructor: no named arguments' => [
+ DummyWithMethods::class,
+ '__construct',
+ [
+ 'value 1',
+ 'value 2',
+ ],
+ [
+ 'value 1',
+ 'value 2',
+ ],
+ ];
+
+ yield 'constructor: named arguments' => [
+ DummyWithMethods::class,
+ '__construct',
+ [
+ 'foo1' => 'value 1',
+ 'foo2' => 'value 2',
+ ],
+ [
+ 'foo1' => 'value 1',
+ 'foo2' => 'value 2',
+ ],
+ ];
+
+ yield 'constructor: named arguments in wrong order' => [
+ DummyWithMethods::class,
+ '__construct',
+ [
+ 'foo2' => 'value 2',
+ 'foo1' => 'value 1',
+ ],
+ [
+ 'foo1' => 'value 1',
+ 'foo2' => 'value 2',
+ ],
+ ];
+
+ yield 'constructor: mix of anonymous and named arguments' => [
+ DummyWithMethods::class,
+ '__construct',
+ [
+ 'value 1',
+ 'foo2' => 'value 2',
+ ],
+ [
+ 'value 1',
+ 'foo2' => 'value 2',
+ ],
+ ];
+
+ yield 'constructor: mix of anonymous and named arguments in wrong order' => [
+ DummyWithMethods::class,
+ '__construct',
+ [
+ 'foo2' => 'value 2',
+ 'value 1',
+ ],
+ [
+ 'value 1',
+ 'foo2' => 'value 2',
+ ],
+ ];
+
+ yield 'static factory: no named arguments' => [
+ DummyWithMethods::class,
+ 'create',
+ [
+ 'value 1',
+ 'value 2',
+ ],
+ [
+ 'value 1',
+ 'value 2',
+ ],
+ ];
+
+ yield 'static factory: named arguments' => [
+ DummyWithMethods::class,
+ 'create',
+ [
+ 'foo1' => 'value 1',
+ 'foo2' => 'value 2',
+ ],
+ [
+ 'foo1' => 'value 1',
+ 'foo2' => 'value 2',
+ ],
+ ];
+
+ yield 'static factory: named arguments in wrong order' => [
+ DummyWithMethods::class,
+ 'create',
+ [
+ 'foo2' => 'value 2',
+ 'foo1' => 'value 1',
+ ],
+ [
+ 'foo1' => 'value 1',
+ 'foo2' => 'value 2',
+ ],
+ ];
+
+ yield 'static factory: mix of anonymous and named arguments' => [
+ DummyWithMethods::class,
+ 'create',
+ [
+ 'value 1',
+ 'foo2' => 'value 2',
+ ],
+ [
+ 'value 1',
+ 'foo2' => 'value 2',
+ ],
+ ];
+
+ yield 'static factory: mix of anonymous and named arguments in wrong order' => [
+ DummyWithMethods::class,
+ 'create',
+ [
+ 'foo2' => 'value 2',
+ 'value 1',
+ ],
+ [
+ 'value 1',
+ 'foo2' => 'value 2',
+ ],
+ ];
+
+ yield 'method call: no named arguments' => [
+ DummyWithMethods::class,
+ 'bar',
+ [
+ 'value 1',
+ 'value 2',
+ ],
+ [
+ 'value 1',
+ 'value 2',
+ ],
+ ];
+
+ yield 'method call: named arguments' => [
+ DummyWithMethods::class,
+ 'bar',
+ [
+ 'bar1' => 'value 1',
+ 'bar2' => 'value 2',
+ ],
+ [
+ 'bar1' => 'value 1',
+ 'bar2' => 'value 2',
+ ],
+ ];
+
+ yield 'method call: named arguments in wrong order' => [
+ DummyWithMethods::class,
+ 'bar',
+ [
+ 'bar2' => 'value 2',
+ 'bar1' => 'value 1',
+ ],
+ [
+ 'bar1' => 'value 1',
+ 'bar2' => 'value 2',
+ ],
+ ];
+
+ yield 'method call: mix of anonymous and named arguments' => [
+ DummyWithMethods::class,
+ 'bar',
+ [
+ 'value 1',
+ 'bar2' => 'value 2',
+ ],
+ [
+ 'value 1',
+ 'bar2' => 'value 2',
+ ],
+ ];
+
+ yield 'method call: mix of anonymous and named arguments in wrong order' => [
+ DummyWithMethods::class,
+ 'bar',
+ [
+ 'bar2' => 'value 2',
+ 'value 1',
+ ],
+ [
+ 'value 1',
+ 'bar2' => 'value 2',
+ ],
+ ];
+
+ yield 'with variadic argument' => [
+ DummyWithMethods::class,
+ 'methodWithVariadic',
+ [
+ 'baz2' => 'value 2',
+ 'value 1',
+ 'value 4',
+ 'baz3' => 'value 3',
+ 'value 5',
+ ],
+ [
+ 'value 1',
+ 'baz2' => 'value 2',
+ 'value 4',
+ 'value 3',
+ 'value 5',
+ ],
+ ];
+
+ yield 'with missing arguments that have default values' => [
+ DummyWithMethods::class,
+ 'methodWithDefaultValues',
+ [
+ 'baz2' => 'value 2',
+ ],
+ [
+ 'value 1',
+ 'baz2' => 'value 2',
+ ],
+ ];
+
+ yield 'with method that does not exist' => [
+ EmptyDummy::class,
+ '__construct',
+ [
+ 'unknown1' => 'value 1',
+ 'unknown2' => 'value 2',
+ ],
+ [
+ 'unknown1' => 'value 1',
+ 'unknown2' => 'value 2',
+ ],
+ ];
+
+ yield 'with numeric string keys' => [
+ DummyWithMethods::class,
+ '__construct',
+ [
+ '0' => 'value 1',
+ '1' => 'value 2',
+ ],
+ [
+ '0' => 'value 1',
+ '1' => 'value 2',
+ ],
+ ];
+
+ yield 'with null passed to an argument that has nullable type' => [
+ DummyWithMethods::class,
+ 'methodWithNullables',
+ [
+ 'bar1' => 'hello',
+ 'bar2' => null,
+ ],
+ [
+ 'bar1' => 'hello',
+ 'bar2' => null,
+ ],
+ ];
+ }
+
+ public function testThrowsExceptionWhenResolvingUnknownArguments()
+ {
+ $resolver = new NamedArgumentsResolver();
+
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessage('Unknown arguments for Nelmio\Alice\Entity\DummyWithMethods::bar(): $unknown1, $unknown2.');
+
+ $resolver->resolveArguments([
+ 'bar1' => 'value 1',
+ 'bar2' => 'value 2',
+ 'unknown1' => 'value 3',
+ 'unknown2' => 'value 4',
+ ], DummyWithMethods::class, 'bar');
+ }
+
+ public function testThrowsExceptionWhenMissingArgumentsDontHaveDefaultValues()
+ {
+ $resolver = new NamedArgumentsResolver();
+
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessage('Argument $bar1 of Nelmio\Alice\Entity\DummyWithMethods::bar() is not passed a value and does not define a default one.');
+
+ $resolver->resolveArguments([], DummyWithMethods::class, 'bar');
+ }
+}
diff --git a/tests/Loader/LoaderIntegrationTest.php b/tests/Loader/LoaderIntegrationTest.php
index 08242b283..504e0bcb5 100644
--- a/tests/Loader/LoaderIntegrationTest.php
+++ b/tests/Loader/LoaderIntegrationTest.php
@@ -1532,19 +1532,6 @@ public function provideFixturesToInstantiate()
new FixtureEntity\Instantiator\DummyWithExplicitDefaultConstructor(),
];
-// yield 'with named constructor - use factory function' => [
-// [
-// FixtureEntity\Instantiator\DummyWithNamedConstructor::class => [
-// 'dummy' => [
-// '__construct' => [
-// 'namedConstruct' => [],
-// ],
-// ],
-// ],
-// ],
-// FixtureEntity\Instantiator\DummyWithNamedConstructor::namedConstruct(),
-// ];
-
yield 'with default constructor and optional parameters without parameters - use constructor function' => [
[
FixtureEntity\Instantiator\DummyWithOptionalParameterInConstructor::class => [
@@ -1601,107 +1588,6 @@ public function provideFixturesToInstantiate()
new FixtureEntity\Instantiator\DummyWithRequiredParameterInConstructor(100),
];
-// yield 'with named constructor and optional parameters with no parameters - use factory function' => [
-// [
-// FixtureEntity\Instantiator\DummyWithNamedConstructorAndOptionalParameters::class => [
-// 'dummy' => [
-// '__construct' => [
-// 'namedConstruct' => [],
-// ],
-// ],
-// ],
-// ],
-// FixtureEntity\Instantiator\DummyWithNamedConstructorAndOptionalParameters::namedConstruct(),
-// ];
-//
-// yield 'with named constructor and optional parameters with parameters - use factory function' => [
-// [
-// FixtureEntity\Instantiator\DummyWithNamedConstructorAndOptionalParameters::class => [
-// 'dummy' => [
-// '__construct' => [
-// 'namedConstruct' => [
-// 100,
-// ],
-// ],
-// ],
-// ],
-// ],
-// FixtureEntity\Instantiator\DummyWithNamedConstructorAndOptionalParameters::namedConstruct(100),
-// ];
-//
-// yield 'with named constructor and optional parameters with parameters and unique value - use factory function' => [
-// [
-// FixtureEntity\Instantiator\DummyWithNamedConstructorAndOptionalParameters::class => [
-// 'dummy' => [
-// '__construct' => [
-// 'namedConstruct' => [
-// '0 (unique)' => 100,
-// ],
-// ],
-// ],
-// ],
-// ],
-// FixtureEntity\Instantiator\DummyWithNamedConstructorAndOptionalParameters::namedConstruct(100),
-// ];
-//
-// yield 'with named constructor and required parameters with no parameters - throw exception' => [
-// [
-// FixtureEntity\Instantiator\DummyWithNamedConstructorAndRequiredParameters::class => [
-// 'dummy' => [
-// '__construct' => [
-// 'namedConstruct' => [],
-// ],
-// ],
-// ],
-// ],
-// 'An error occurred while generating the fixture "dummy" (Nelmio\Alice\Entity\Instantiator\DummyWithNamedConstructorAndRequiredParameters): Could not instantiate fixture "dummy".',
-// GenerationThrowable::class,
-// ];
-//
-// yield 'with named constructor and required parameters with parameters - use factory function' => [
-// [
-// FixtureEntity\Instantiator\DummyWithNamedConstructorAndRequiredParameters::class => [
-// 'dummy' => [
-// '__construct' => [
-// 'namedConstruct' => [
-// 100,
-// ],
-// ],
-// ],
-// ],
-// ],
-// FixtureEntity\Instantiator\DummyWithNamedConstructorAndRequiredParameters::namedConstruct(100),
-// ];
-//
-// yield 'with named constructor and required parameters with named parameters - use factory function' => [
-// [
-// FixtureEntity\Instantiator\DummyWithNamedConstructorAndRequiredParameters::class => [
-// 'dummy' => [
-// '__construct' => [
-// 'namedConstruct' => [
-// 'param' => 100,
-// ],
-// ],
-// ],
-// ],
-// ],
-// FixtureEntity\Instantiator\DummyWithNamedConstructorAndRequiredParameters::namedConstruct(100),
-// ];
-//
-// yield 'with unknown named constructor' => [
-// [
-// FixtureEntity\Instantiator\DummyWithDefaultConstructor::class => [
-// 'dummy' => [
-// '__construct' => [
-// 'unknown' => [],
-// ],
-// ],
-// ],
-// ],
-// 'An error occurred while generating the fixture "dummy" (Nelmio\Alice\Entity\Instantiator\DummyWithDefaultConstructor): Could not instantiate fixture "dummy".',
-// GenerationThrowable::class,
-// ];
-//
yield 'with private constructor – throw exception' => [
[
FixtureEntity\Instantiator\DummyWithPrivateConstructor::class => [
@@ -1721,21 +1607,7 @@ public function provideFixturesToInstantiate()
'An error occurred while generating the fixture "dummy" (Nelmio\Alice\Entity\Instantiator\DummyWithProtectedConstructor): Could not instantiate "dummy", the constructor of "Nelmio\Alice\Entity\Instantiator\DummyWithProtectedConstructor" is not public.',
GenerationThrowable::class,
];
-//
-// yield 'with private named constructor – throw exception' => [
-// [
-// FixtureEntity\Instantiator\DummyWithNamedPrivateConstructor::class => [
-// 'dummy' => [
-// '__construct' => [
-// 'namedConstruct' => [],
-// ],
-// ],
-// ],
-// ],
-// 'An error occurred while generating the fixture "dummy" (Nelmio\Alice\Entity\Instantiator\DummyWithNamedPrivateConstructor): Could not instantiate fixture "dummy".',
-// GenerationThrowable::class,
-// ];
-//
+
yield 'with default constructor but specified no constructor – use reflection' => [
[
FixtureEntity\Instantiator\DummyWithDefaultConstructor::class => [
@@ -1847,6 +1719,61 @@ public function provideFixturesToInstantiate()
],
(new ReflectionClass(FixtureEntity\Instantiator\DummyWithNamedPrivateConstructor::class))->newInstanceWithoutConstructor(),
];
+
+ yield 'with constructor named parameters' => [
+ [
+ FixtureEntity\DummyWithMethods::class => [
+ 'dummy' => [
+ '__construct' => [
+ 'foo2' => 'value 2',
+ 'foo1' => 'value 1',
+ ],
+ ],
+ ],
+ ],
+ new FixtureEntity\DummyWithMethods('value 1', 'value 2'),
+ ];
+
+ yield 'with factory named parameters' => [
+ [
+ FixtureEntity\DummyWithMethods::class => [
+ 'dummy' => [
+ '__factory' => [
+ 'create' => [
+ 'foo2' => 'value 2',
+ 'foo1' => 'value 1',
+ ],
+ ],
+ ],
+ ],
+ ],
+ FixtureEntity\DummyWithMethods::create('value 1', 'value 2'),
+ ];
+
+ $expected = new FixtureEntity\DummyWithMethods('value 1', 'value 2');
+ $expected->bar('value 3', 'value 4');
+
+ yield 'with method call named parameters' => [
+ [
+ FixtureEntity\DummyWithMethods::class => [
+ 'dummy' => [
+ '__construct' => [
+ 'foo2' => 'value 2',
+ 'foo1' => 'value 1',
+ ],
+ '__calls' => [
+ [
+ 'bar' => [
+ 'bar2' => 'value 4',
+ 'bar1' => 'value 3',
+ ],
+ ]
+ ],
+ ],
+ ],
+ ],
+ $expected,
+ ];
}
public function provideLegacyFixturesToInstantiate()
diff --git a/tests/Parser/Chainable/JsonParserTest.php b/tests/Parser/Chainable/JsonParserTest.php
index f3639d0d5..335b17f67 100644
--- a/tests/Parser/Chainable/JsonParserTest.php
+++ b/tests/Parser/Chainable/JsonParserTest.php
@@ -143,6 +143,33 @@ public function testParsingEmptyFileResultsInEmptySet()
$this->assertSame([], $actual);
}
+ public function testParseReturnsNamedParameters()
+ {
+ $actual = $this->parser->parse(self::$dir.'/named_parameters.json');
+
+ $this->assertSame(
+ [
+ 'Nelmio\Alice\DummyWithMethods' => [
+ 'dummy_with_methods' => [
+ '__construct' => [
+ '$foo1' => 'foo1',
+ '$foo2' => 'foo2',
+ ],
+ '__calls' => [
+ [
+ 'bar' => [
+ '$bar1' => 'bar1',
+ '$bar2' => 'bar2',
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ $actual
+ );
+ }
+
public function testThrowsAnExceptionIfInvalidJson()
{
$this->expectException(UnparsableFileException::class);
diff --git a/tests/Parser/Chainable/PhpParserTest.php b/tests/Parser/Chainable/PhpParserTest.php
index 70da7b850..abf39be7e 100644
--- a/tests/Parser/Chainable/PhpParserTest.php
+++ b/tests/Parser/Chainable/PhpParserTest.php
@@ -142,6 +142,33 @@ public function testParsingEmptyFileResultsInEmptySet()
$this->assertSame([], $actual);
}
+ public function testParseReturnsNamedParameters()
+ {
+ $actual = $this->parser->parse(self::$dir.'/named_parameters.php');
+
+ $this->assertSame(
+ [
+ 'Nelmio\Alice\DummyWithMethods' => [
+ 'dummy_with_methods' => [
+ '__construct' => [
+ '$foo1' => 'foo1',
+ '$foo2' => 'foo2',
+ ],
+ '__calls' => [
+ [
+ 'bar' => [
+ '$bar1' => 'bar1',
+ '$bar2' => 'bar2',
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ $actual
+ );
+ }
+
public function testThrowsAnExceptionIfNoArrayReturnedInParsedFile()
{
$this->expectException(\TypeError::class);
diff --git a/tests/Parser/Chainable/YamlParserTest.php b/tests/Parser/Chainable/YamlParserTest.php
index f9e20854b..4c5f6608a 100644
--- a/tests/Parser/Chainable/YamlParserTest.php
+++ b/tests/Parser/Chainable/YamlParserTest.php
@@ -222,6 +222,36 @@ public function testParsingEmptyFileResultsInEmptySet()
$this->assertSame([], $actual);
}
+ public function testParseReturnsNamedParameters()
+ {
+ $symfonyParser = new SymfonyYamlParser();
+
+ $parser = new YamlParser($symfonyParser);
+ $actual = $parser->parse(self::$dir.'/named_parameters.yml');
+
+ $this->assertSame(
+ [
+ 'Nelmio\Alice\DummyWithMethods' => [
+ 'dummy_with_methods' => [
+ '__construct' => [
+ '$foo1' => 'foo1',
+ '$foo2' => 'foo2',
+ ],
+ '__calls' => [
+ [
+ 'bar' => [
+ '$bar1' => 'bar1',
+ '$bar2' => 'bar2',
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ $actual
+ );
+ }
+
public function testThrowsAnExceptionIfFileNotParsable()
{
try {