diff --git a/README.md b/README.md index fc51ca1..1ab32cc 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,8 @@ class SomeTest extends ConfigurableKernelTestCase } ``` +#### Attributes + An alternative to passing a `config` closure in the `options` array to `ConfigurableKernelTestCase::bootKernel()` is to use attributes for the kernel configuration. @@ -155,6 +157,42 @@ class SomeTest extends ConfigurableKernelTestCase > [!TIP] > All attributes can be used on class *and* test method level. +#### Data Provider + +You can also use the `RegisterBundle`, `ConfigureContainer`, `ConfigureExtension`, or `RegisterCompilerPass` classes +to configure the kernel in a data provider. + +```php +use Neusta\Pimcore\TestingFramework\Test\Attribute\ConfigureExtension; +use Neusta\Pimcore\TestingFramework\Test\ConfigurableKernelTestCase; + +class SomeTest extends ConfigurableKernelTestCase +{ + public function provideTestData(): iterable + { + yield [ + 'some value', + new ConfigureExtension('some_extension', ['config' => 'some value']), + ]; + + yield [ + new ConfigureExtension('some_extension', ['config' => 'other value']), + 'other value', + ]; + } + + /** @dataProvider provideTestData */ + public function test_something(string $expected): void + { + self::assertSame($expected, self::getContainer()->getParameter('config')); + } +} +``` + +> [!TIP] +> The kernel configuration objects are *not* passed as arguments to the test method, +> which means you can use them anywhere between your provided real test data. + ### Integration Tests With a Database If you write integration tests that use the database, we've got you covered too. diff --git a/src/Kernel/TestKernel.php b/src/Kernel/TestKernel.php index 55284df..35a6e50 100644 --- a/src/Kernel/TestKernel.php +++ b/src/Kernel/TestKernel.php @@ -27,7 +27,7 @@ public function addTestBundle(string $bundleClass): void } /** - * @param string|callable(ContainerBuilder):void $config path to a config file or a callable which get the {@see ContainerBuilder} as its first argument + * @param string|callable(ContainerBuilder):void $config path to a config file or a callable which gets the {@see ContainerBuilder} as its first argument */ public function addTestConfig(string|callable $config): void { diff --git a/src/Test/Attribute/ConfigureContainer.php b/src/Test/Attribute/ConfigureContainer.php index 4c6879e..a7d2a04 100644 --- a/src/Test/Attribute/ConfigureContainer.php +++ b/src/Test/Attribute/ConfigureContainer.php @@ -4,15 +4,16 @@ namespace Neusta\Pimcore\TestingFramework\Test\Attribute; use Neusta\Pimcore\TestingFramework\Kernel\TestKernel; +use Symfony\Component\DependencyInjection\ContainerBuilder; #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] final class ConfigureContainer implements KernelConfiguration { /** - * @param string $config path to a config file + * @param string|\Closure(ContainerBuilder):void $config path to a config file or a closure which gets the {@see ContainerBuilder} as its first argument */ public function __construct( - private readonly string $config, + private readonly string|\Closure $config, ) { } diff --git a/src/Test/ConfigurableKernelTestCase.php b/src/Test/ConfigurableKernelTestCase.php index 5591085..36a3039 100644 --- a/src/Test/ConfigurableKernelTestCase.php +++ b/src/Test/ConfigurableKernelTestCase.php @@ -5,7 +5,7 @@ use Neusta\Pimcore\TestingFramework\Kernel\TestKernel; use Neusta\Pimcore\TestingFramework\Test\Attribute\KernelConfiguration; -use Neusta\Pimcore\TestingFramework\Test\Reflection\TestAttributeProvider; +use PHPUnit\Framework\TestCase; use Pimcore\Test\KernelTestCase; abstract class ConfigurableKernelTestCase extends KernelTestCase @@ -37,7 +37,33 @@ protected static function createKernel(array $options = []): TestKernel */ public function _getKernelConfigurationFromAttributes(): void { - self::$kernelConfigurations = (new TestAttributeProvider($this))->getKernelConfigurationAttributes(); + $class = new \ReflectionClass($this); + $method = $class->getMethod($this->getName(false)); + + $attributes = []; + foreach ($class->getAttributes(KernelConfiguration::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) { + $attributes[] = $attribute->newInstance(); + } + + foreach ($method->getAttributes(KernelConfiguration::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) { + $attributes[] = $attribute->newInstance(); + } + + if ([] !== $providedData = $this->getProvidedData()) { + foreach ($providedData as $data) { + if ($data instanceof KernelConfiguration) { + $attributes[] = $data; + } + } + + // remove it from the arguments passed to the test method + (new \ReflectionProperty(TestCase::class, 'data'))->setValue($this, array_values(array_filter( + $providedData, + fn ($data) => !$data instanceof KernelConfiguration, + ))); + } + + self::$kernelConfigurations = $attributes; } protected function tearDown(): void diff --git a/src/Test/Reflection/TestAttributeProvider.php b/src/Test/Reflection/TestAttributeProvider.php deleted file mode 100644 index e688e99..0000000 --- a/src/Test/Reflection/TestAttributeProvider.php +++ /dev/null @@ -1,49 +0,0 @@ -test = new \ReflectionMethod($test, $test->getName(false)); - } - - /** - * @return list - */ - public function getKernelConfigurationAttributes(): array - { - $attributes = []; - foreach ($this->getAttributes($this->test->getDeclaringClass(), KernelConfiguration::class) as $attribute) { - $attributes[] = $attribute->newInstance(); - } - - foreach ($this->getAttributes($this->test, KernelConfiguration::class) as $attribute) { - $attributes[] = $attribute->newInstance(); - } - - return $attributes; - } - - /** - * @template T of object - * - * @param class-string $attribute - * - * @return iterable<\ReflectionAttribute> - */ - private function getAttributes(\ReflectionClass|\ReflectionMethod $source, string $attribute): iterable - { - yield from $source->getAttributes($attribute, \ReflectionAttribute::IS_INSTANCEOF); - } -} diff --git a/tests/Functional/ContainerConfigurationTest.php b/tests/Functional/ContainerConfigurationTest.php index 1322708..6c4ced0 100644 --- a/tests/Functional/ContainerConfigurationTest.php +++ b/tests/Functional/ContainerConfigurationTest.php @@ -41,6 +41,31 @@ public function different_configuration_formats(string|callable $config): void self::assertContainerConfiguration(self::getContainer()); } + public function provideDifferentConfigurationFormatsViaKernelConfigurationObject(): iterable + { + yield 'YAML' => [new ConfigureContainer(__DIR__ . '/../Fixtures/Resources/ConfigurationBundle/config.yaml')]; + yield 'XML' => [new ConfigureContainer(__DIR__ . '/../Fixtures/Resources/ConfigurationBundle/config.xml')]; + yield 'PHP' => [new ConfigureContainer(__DIR__ . '/../Fixtures/Resources/ConfigurationBundle/config.php')]; + yield 'Callable' => [new ConfigureContainer(function (ContainerBuilder $container) { + $container->loadFromExtension('configuration', [ + 'foo' => 'value1', + 'bar' => ['value2', 'value3'], + ]); + + $container->register('something', \stdClass::class)->setPublic(true); + })]; + } + + /** + * @test + * + * @dataProvider provideDifferentConfigurationFormatsViaKernelConfigurationObject + */ + public function different_configuration_formats_via_data_provider(): void + { + self::assertContainerConfiguration(self::getContainer()); + } + /** * @test */ @@ -70,8 +95,8 @@ public function configuration_in_php_via_attribute(): void public static function assertContainerConfiguration(ContainerInterface $container): void { - self::assertEquals('value1', $container->getParameter('configuration.foo')); - self::assertEquals(['value2', 'value3'], $container->getParameter('configuration.bar')); + self::assertSame('value1', $container->getParameter('configuration.foo')); + self::assertSame(['value2', 'value3'], $container->getParameter('configuration.bar')); self::assertInstanceOf(\stdClass::class, $container->get('something', ContainerInterface::NULL_ON_INVALID_REFERENCE)); } } diff --git a/tests/Functional/DataProviderTest.php b/tests/Functional/DataProviderTest.php new file mode 100644 index 0000000..21d0604 --- /dev/null +++ b/tests/Functional/DataProviderTest.php @@ -0,0 +1,62 @@ + [ + new RegisterBundle(ConfigurationBundle::class), + new ConfigureExtension('configuration', [ + 'foo' => 'value1', + 'bar' => ['value2', 'value3'], + ]), + 'value1', + 'value2', + 'value3', + ]; + + yield 'kernel configuration at the end' => [ + 'foo', + 'bar', + 'baz', + new RegisterBundle(ConfigurationBundle::class), + new ConfigureExtension('configuration', [ + 'foo' => 'foo', + 'bar' => ['bar', 'baz'], + ]), + ]; + + yield 'kernel configuration in between other provided data' => [ + 'test1', + new RegisterBundle(ConfigurationBundle::class), + 'test2', + new ConfigureExtension('configuration', [ + 'foo' => 'test1', + 'bar' => ['test2', 'test3'], + ]), + 'test3', + ]; + } + + /** + * @test + * + * @dataProvider provideData + */ + public function configuration_via_data_provider(string $value1, string $value2, string $value3): void + { + $container = self::getContainer(); + + self::assertSame($value1, $container->getParameter('configuration.foo')); + self::assertSame([$value2, $value3], $container->getParameter('configuration.bar')); + } +} diff --git a/tests/Functional/ExtensionConfigurationTest.php b/tests/Functional/ExtensionConfigurationTest.php index ea5d97f..38f39f4 100644 --- a/tests/Functional/ExtensionConfigurationTest.php +++ b/tests/Functional/ExtensionConfigurationTest.php @@ -26,8 +26,8 @@ public function extension_configuration(): void $container = self::getContainer(); - self::assertEquals('value1', $container->getParameter('configuration.foo')); - self::assertEquals(['value2', 'value3'], $container->getParameter('configuration.bar')); + self::assertSame('value1', $container->getParameter('configuration.foo')); + self::assertSame(['value2', 'value3'], $container->getParameter('configuration.bar')); } /** @@ -41,7 +41,7 @@ public function extension_configuration_via_attributes(): void { $container = self::getContainer(); - self::assertEquals('value1', $container->getParameter('configuration.foo')); - self::assertEquals(['value2', 'value3'], $container->getParameter('configuration.bar')); + self::assertSame('value1', $container->getParameter('configuration.foo')); + self::assertSame(['value2', 'value3'], $container->getParameter('configuration.bar')); } }