From 045e14f5310eae98b776a949d1fa92a3ef9f7665 Mon Sep 17 00:00:00 2001 From: Nicolas PHILIPPE Date: Wed, 9 Nov 2022 19:30:03 +0100 Subject: [PATCH] [feat] Allow to use foundry without Doctrine --- .github/workflows/ci.yml | 22 --------- docs/index.rst | 39 ++++----------- phpunit-dama-doctrine.xml.dist | 2 +- phpunit.xml.dist | 2 +- .../ChainManagerRegistryPass.php | 4 -- src/ChainManagerRegistry.php | 4 -- src/Test/Factories.php | 2 +- src/Test/TestState.php | 45 ++++++++++++++--- tests/Fixtures/Kernel.php | 36 +++++++++++--- .../Functional/Bundle/Maker/MakerTestCase.php | 4 ++ .../WithDoctrineDisabledKernelTest.php | 48 +++++++++++++++++++ tests/bootstrap.php | 3 -- 12 files changed, 134 insertions(+), 77 deletions(-) create mode 100644 tests/Functional/WithDoctrineDisabledKernelTest.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f35799bbf..06dd30ad3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,7 +75,6 @@ jobs: - name: 'Test: MySQL' run: vendor/bin/simple-phpunit -v env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7 - name: 'Test: MySQL, FoundryBundle' @@ -87,7 +86,6 @@ jobs: - name: 'Test: MySQL, DAMABundle' run: vendor/bin/simple-phpunit -v --configuration phpunit-dama-doctrine.xml.dist env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7 - name: 'Test: MySQL, FoundryBundle, DAMABundle' @@ -99,21 +97,18 @@ jobs: - name: 'Test: MySQL, DoctrineMigrationsBundle' run: vendor/bin/simple-phpunit -v env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 USE_MIGRATIONS: 1 DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7 - name: 'Test: MySQL, DoctrineMigrationsBundle, DAMABundle' run: vendor/bin/simple-phpunit -v --configuration phpunit-dama-doctrine.xml.dist env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 USE_MIGRATIONS: 1 DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7 - name: 'Test: PostgreSQL' run: vendor/bin/simple-phpunit -v env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: postgresql://postgres:1234@127.0.0.1:5432/zenstruck_foundry?charset=utf8 - name: 'Test: PostgreSQL, FoundryBundle' @@ -136,7 +131,6 @@ jobs: - name: 'Test: SQLite' run: vendor/bin/simple-phpunit -v env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: sqlite:///%kernel.cache_dir%/app.db - name: 'Test: SQLite, FoundryBundle' @@ -148,20 +142,17 @@ jobs: - name: 'Test: SQLite, DAMABundle' run: vendor/bin/simple-phpunit -v --configuration phpunit-dama-doctrine.xml.dist env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: sqlite:///%kernel.cache_dir%/app.db - name: 'Test: SQLite, FoundryBundle, DAMABundle' run: vendor/bin/simple-phpunit -v --configuration phpunit-dama-doctrine.xml.dist env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 # USE_FOUNDRY_BUNDLE: 1 DATABASE_URL: sqlite:///%kernel.cache_dir%/app.db - name: 'Test: MySQL, Mongo' run: vendor/bin/simple-phpunit -v env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7 MONGO_URL: mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb @@ -175,14 +166,12 @@ jobs: - name: 'Test: MySQL, Mongo, DAMABundle' run: vendor/bin/simple-phpunit -v --configuration phpunit-dama-doctrine.xml.dist env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7 MONGO_URL: mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb - name: 'Test: Mongo standalone' run: vendor/bin/simple-phpunit -v env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 MONGO_URL: mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb code-coverage: @@ -231,7 +220,6 @@ jobs: - name: 'Coverage: MySQL' run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=mysql.clover env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7 - name: 'Coverage: MySQL, FoundryBundle' @@ -243,7 +231,6 @@ jobs: - name: 'Coverage: MySQL, DAMABundle' run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=mysql-dama.clover --configuration phpunit-dama-doctrine.xml.dist env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7 - name: 'Coverage: MySQL, FoundryBundle, DAMABundle' @@ -255,21 +242,18 @@ jobs: - name: 'Test: MySQL, DoctrineMigrationsBundle' run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=mysql-migrations.clover env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 USE_MIGRATIONS: 1 DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7 - name: 'Test: MySQL, DoctrineMigrationsBundle, DAMABundle' run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=mysql-migrations-dama.clover --configuration phpunit-dama-doctrine.xml.dist env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 USE_MIGRATIONS: 1 DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7 - name: 'Coverage: PostgreSQL' run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=postgres.clover env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: postgresql://postgres:1234@127.0.0.1:5432/zenstruck_foundry?charset=utf8 - name: 'Coverage: PostgreSQL, FoundryBundle' @@ -292,7 +276,6 @@ jobs: - name: 'Coverage: SQLite' run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=sqlite.clover env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: sqlite:///%kernel.cache_dir%/app.db - name: 'Coverage: SQLite, FoundryBundle' @@ -304,20 +287,17 @@ jobs: - name: 'Coverage: SQLite, DAMABundle' run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=sqlite-dama.clover --configuration phpunit-dama-doctrine.xml.dist env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: sqlite:///%kernel.cache_dir%/app.db - name: 'Coverage: SQLite, FoundryBundle, DAMABundle' run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=sqlite-foundry-dama.clover --configuration phpunit-dama-doctrine.xml.dist env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 # USE_FOUNDRY_BUNDLE: 1 DATABASE_URL: sqlite:///%kernel.cache_dir%/app.db - name: 'Test: MySQL, Mongo' run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=mysql-mongo.clover env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7 MONGO_URL: mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb @@ -331,14 +311,12 @@ jobs: - name: 'Test: MySQL, Mongo, DAMABundle' run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=mysql-mongo-dama.clover --configuration phpunit-dama-doctrine.xml.dist env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7 MONGO_URL: mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb - name: 'Test: Mongo standalone' run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=mongo.clover env: - SYMFONY_DEPRECATIONS_HELPER: max[direct]=0&max[self]=99999 MONGO_URL: mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb - name: Publish coverage report to Codecov diff --git a/docs/index.rst b/docs/index.rst index 3d3f1a188..d4f8f7c24 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1638,46 +1638,27 @@ here. The easiest work-around is to make the test an instance of ``Symfony\Bundle\FrameworkBundle\Test\KernelTestCase`` so the container is available. -Test-Only Configuration -~~~~~~~~~~~~~~~~~~~~~~~ +Using in Unit Tests +~~~~~~~~~~~~~~~~~~~ + +When using foundry in unit tests, by using ``PHPUnit\Framework\TestCase``, Foundry simply creates the object instancies +but does not try to persist them (this is also true for any object not managed by Doctrine). -Foundry can be configured statically, with pure PHP, in your ``tests/bootstrap.php``. This is useful if you have a mix -of Kernel and `non-Kernel tests`_ or if `Using Without the Bundle`_: +You can still configure Foundry statically: .. code-block:: php // tests/bootstrap.php // ... - // configure a default instantiator - Zenstruck\Foundry\Test\TestState::setInstantiator( - (new Zenstruck\Foundry\Instantiator()) + Zenstruck\Foundry\Test\TestState::configure( + instantiator: (new Zenstruck\Foundry\Instantiator()) ->withoutConstructor() ->allowExtraAttributes() - ->alwaysForceProperties() + ->alwaysForceProperties(), + faker: Faker\Factory::create('fr_FR') ); - // configure a custom faker - Zenstruck\Foundry\Test\TestState::setFaker(Faker\Factory::create('fr_FR')); - - // enable auto-refreshing "globally" - Zenstruck\Foundry\Test\TestState::enableDefaultProxyAutoRefresh(); - - // disable auto-refreshing "globally" - Zenstruck\Foundry\Test\TestState::disableDefaultProxyAutoRefresh(); - -.. note:: - - If using `bundle configuration`_ as well, *test-only configuration* will override the - bundle configuration. - -Using without the Bundle -~~~~~~~~~~~~~~~~~~~~~~~~ - -The provided bundle is not strictly required to use Foundry for tests. You can have all your factories, stories, and -configuration live in your ``tests/`` directory. You can configure foundry with -`Test-Only Configuration`_. - .. _stories: Stories diff --git a/phpunit-dama-doctrine.xml.dist b/phpunit-dama-doctrine.xml.dist index 81a68ab06..1e7a491d4 100644 --- a/phpunit-dama-doctrine.xml.dist +++ b/phpunit-dama-doctrine.xml.dist @@ -12,7 +12,7 @@ - + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b1d4bb9b3..9d1b27c3b 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -11,7 +11,7 @@ - + diff --git a/src/Bundle/DependencyInjection/ChainManagerRegistryPass.php b/src/Bundle/DependencyInjection/ChainManagerRegistryPass.php index 383649fab..b9517d415 100644 --- a/src/Bundle/DependencyInjection/ChainManagerRegistryPass.php +++ b/src/Bundle/DependencyInjection/ChainManagerRegistryPass.php @@ -25,10 +25,6 @@ public function process(ContainerBuilder $container): void $managerRegistries[] = new Reference('doctrine_mongodb'); } - if (0 === \count($managerRegistries)) { - throw new \LogicException('Neither doctrine/orm nor mongodb-odm are present.'); - } - $container->getDefinition(ChainManagerRegistry::class) ->setArgument('$managerRegistries', $managerRegistries) ; diff --git a/src/ChainManagerRegistry.php b/src/ChainManagerRegistry.php index 0af03cd75..fbd4c4acd 100644 --- a/src/ChainManagerRegistry.php +++ b/src/ChainManagerRegistry.php @@ -18,10 +18,6 @@ final class ChainManagerRegistry implements ManagerRegistry /** @param list $managerRegistries */ public function __construct(array $managerRegistries) { - if (0 === \count($managerRegistries)) { - throw new \InvalidArgumentException('no manager registry provided'); - } - $this->managerRegistries = $managerRegistries; } diff --git a/src/Test/Factories.php b/src/Test/Factories.php index 11de6e79d..f6c1ce703 100644 --- a/src/Test/Factories.php +++ b/src/Test/Factories.php @@ -19,7 +19,7 @@ trait Factories public static function _setUpFactories(): void { if (!\is_subclass_of(static::class, KernelTestCase::class)) { - TestState::bootFoundry(); + TestState::bootFoundryWithoutBundle(); return; } diff --git a/src/Test/TestState.php b/src/Test/TestState.php index 02754f2b9..689244393 100644 --- a/src/Test/TestState.php +++ b/src/Test/TestState.php @@ -9,6 +9,7 @@ use Zenstruck\Foundry\ChainManagerRegistry; use Zenstruck\Foundry\Configuration; use Zenstruck\Foundry\Factory; +use Zenstruck\Foundry\Instantiator; use Zenstruck\Foundry\StoryManager; /** @@ -28,23 +29,43 @@ final class TestState /** @var callable[] */ private static $globalStates = []; + /** + * @deprecated Use TestState::configure() + */ public static function setInstantiator(callable $instantiator): void { + trigger_deprecation('zenstruck\foundry', '1.23', 'Usage of TestState::setInstantiator() is deprecated. Please use TestState::configure().'); + self::$instantiator = $instantiator; } + /** + * @deprecated Use TestState::configure() + */ public static function setFaker(Faker\Generator $faker): void { + trigger_deprecation('zenstruck\foundry', '1.23', 'Usage of TestState::setFaker() is deprecated. Please use TestState::configure().'); + self::$faker = $faker; } + /** + * @deprecated Use bundle configuration + */ public static function enableDefaultProxyAutoRefresh(): void { + trigger_deprecation('zenstruck\foundry', '1.23', 'Usage of TestState::enableDefaultProxyAutoRefresh() is deprecated. Please use bundle configuration under "auto_refresh_proxies" key.'); + self::$defaultProxyAutoRefresh = true; } + /** + * @deprecated Use bundle configuration + */ public static function disableDefaultProxyAutoRefresh(): void { + trigger_deprecation('zenstruck\foundry', '1.23', 'Usage of TestState::disableDefaultProxyAutoRefresh() is deprecated. Please use bundle configuration under "auto_refresh_proxies" key.'); + self::$defaultProxyAutoRefresh = false; } @@ -73,9 +94,9 @@ public static function addGlobalState(callable $callback): void self::$globalStates[] = $callback; } - public static function bootFoundry(?Configuration $configuration = null): void + public static function bootFoundryWithoutBundle(): void { - $configuration = $configuration ?? new Configuration([], [], 'schema', []); + $configuration = new Configuration([], [], 'schema', []); if (self::$instantiator) { $configuration->setInstantiator(self::$instantiator); @@ -91,9 +112,17 @@ public static function bootFoundry(?Configuration $configuration = null): void $configuration->disableDefaultProxyAutoRefresh(); } + self::bootFoundry($configuration); + } + + public static function bootFoundry(Configuration $configuration): void + { Factory::boot($configuration); } + /** + * @internal + */ public static function shutdownFoundry(): void { Factory::shutdown(); @@ -123,6 +152,8 @@ public static function bootFromContainer(ContainerInterface $container): void return; } + trigger_deprecation('zenstruck\foundry', '1.23', 'Usage of foundry without the bundle is deprecated and will not be possible anymore in 2.0.'); + $configuration = new Configuration([], [], 'schema', []); try { @@ -150,10 +181,6 @@ public static function initializeChainManagerRegistry(ContainerInterface $contai $managerRegistries[] = $container->get('doctrine_mongodb'); } - if (0 === \count($managerRegistries)) { - throw new \LogicException('Neither doctrine/orm nor doctrine/mongodb-odm are present.'); - } - return new ChainManagerRegistry($managerRegistries); } @@ -176,4 +203,10 @@ public static function flushGlobalState(?GlobalStateRegistry $globalStateRegistr StoryManager::setGlobalState(); } + + public static function configure(?Instantiator $instantiator = null, ?Faker\Generator $faker = null): void + { + self::$instantiator = $instantiator; + self::$faker = $faker; + } } diff --git a/tests/Fixtures/Kernel.php b/tests/Fixtures/Kernel.php index 158ab9244..4110e7709 100644 --- a/tests/Fixtures/Kernel.php +++ b/tests/Fixtures/Kernel.php @@ -29,11 +29,27 @@ class Kernel extends BaseKernel { use MicroKernelTrait; + /** @var string|null */ + private $databaseUrl; + /** @var string|null */ + private $mongoUrl; + + public function __construct( + bool $useDatabase = true + ) { + if ($useDatabase) { + $this->databaseUrl = \getenv('DATABASE_URL') ?: null; + $this->mongoUrl = \getenv('MONGO_URL') ?: null; + } + + parent::__construct('test', true); + } + public function registerBundles(): iterable { yield new FrameworkBundle(); - if (\getenv('DATABASE_URL')) { + if ($this->databaseUrl) { yield new DoctrineBundle(); } @@ -51,11 +67,19 @@ public function registerBundles(): iterable yield new DoctrineMigrationsBundle(); } - if (\getenv('MONGO_URL')) { + if ($this->mongoUrl) { yield new DoctrineMongoDBBundle(); } } + public function getCacheDir(): string + { + return \sprintf( + "{$this->getProjectDir()}/var/cache/test/%s", + \md5(\json_encode([$this->databaseUrl, $this->mongoUrl])) + ); + } + protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader): void { $c->register(Service::class); @@ -78,7 +102,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'test' => true, ]); - if (\getenv('DATABASE_URL')) { + if ($this->databaseUrl) { $c->loadFromExtension( 'doctrine', [ @@ -104,7 +128,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load $foundryConfig = ['auto_refresh_proxies' => false]; $globalState = []; - if (\getenv('DATABASE_URL')) { + if ($this->databaseUrl) { $globalState[] = TagStory::class; $globalState[] = TagStoryAsInvokableService::class; @@ -113,7 +137,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load } } - if (\getenv('MONGO_URL') && !\getenv('USE_DAMA_DOCTRINE_TEST_BUNDLE')) { + if ($this->mongoUrl && !\getenv('USE_DAMA_DOCTRINE_TEST_BUNDLE')) { $globalState[] = ODMTagStory::class; $globalState[] = ODMTagStoryAsAService::class; } @@ -131,7 +155,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ]); } - if (\getenv('MONGO_URL')) { + if ($this->mongoUrl) { $c->loadFromExtension('doctrine_mongodb', [ 'connections' => [ 'default' => ['server' => '%env(resolve:MONGO_URL)%'], diff --git a/tests/Functional/Bundle/Maker/MakerTestCase.php b/tests/Functional/Bundle/Maker/MakerTestCase.php index 7a8733911..f39781c76 100644 --- a/tests/Functional/Bundle/Maker/MakerTestCase.php +++ b/tests/Functional/Bundle/Maker/MakerTestCase.php @@ -18,6 +18,10 @@ public function skipIfNotUsingFoundryBundle(): void if (!\getenv('USE_FOUNDRY_BUNDLE')) { $this->markTestSkipped('ZenstruckFoundryBundle not enabled.'); } + + if (!\getenv('DOCTRINE_URL') && !\getenv('MONGO_URL')) { + $this->markTestSkipped('Generating factories for classes not managed by doctrine is not supported.'); + } } /** diff --git a/tests/Functional/WithDoctrineDisabledKernelTest.php b/tests/Functional/WithDoctrineDisabledKernelTest.php new file mode 100644 index 000000000..f90ffce3d --- /dev/null +++ b/tests/Functional/WithDoctrineDisabledKernelTest.php @@ -0,0 +1,48 @@ +withoutPersisting()->create(['value' => 'test'])->object(); + Assert::that($address)->isInstanceOf(Address::class); + Assert::that($address->getValue())->is('test'); + + $address = AddressFactory::createOne(['value' => 'test'])->object(); + Assert::that($address)->isInstanceOf(Address::class); + Assert::that($address->getValue())->is('test'); + } + + protected static function createKernel(array $options = []): KernelInterface + { + return new Kernel(false); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index eae8bc83e..e12d5b77f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,10 +1,7 @@ remove(__DIR__.'/../var'); - -TestState::disableDefaultProxyAutoRefresh();