Skip to content

Commit deb7637

Browse files
committed
feat(2.9): deprecate Factories trait and force PHPUnit extension usage (#968)
1 parent 2f426f0 commit deb7637

File tree

42 files changed

+919
-539
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+919
-539
lines changed

UPGRADE-2.7.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ return RectorConfig::configure()
5252
'src',
5353
'tests'
5454
])
55-
->withSets([FoundrySetList::REMOVE_PROXIES])
55+
->withSets([FoundrySetList::FOUNDRY_2_7])
5656
;
5757
```
5858

UPGRADE-2.9.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Migration guide from Foundry 2.8 to 2.9
2+
3+
The main feature of Foundry 2.9 is the deprecation of the `Factories` trait, in favor of the [PHPUnit extension](https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#phpunit-extension)
4+
shipped by Foundry. It was necessary to remember to add the trait in every test class. And in some cases, Foundry could
5+
still work even if the trait wasn’t added to the test, which could lead to subtle bugs. Now, Foundry is globally enabled
6+
once for all.
7+
8+
The trait will be removed in Foundry 3.0, and the extension will be mandatory.
9+
10+
> [!WARNING]
11+
> The PHPUnit extension mechanism was introduced in PHPUnit 10. This means that Foundry 3 won't be compatible
12+
> with PHPUnit 9 anymore (but Foundry 2 will remain compatible with PHPUnit 9).
13+
14+
## How to
15+
16+
> [!IMPORTANT]
17+
> If you're still not using PHPUnit 10 or grater, there is nothing to do (yet!)
18+
19+
Enable Foundry's [PHPUnit extension](https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#phpunit-extension)
20+
in your `phpunit.xml` file:
21+
22+
```xml
23+
<phpunit>
24+
<extensions>
25+
<bootstrap class="Zenstruck\Foundry\PHPUnit\FoundryExtension"/>
26+
</extensions>
27+
</phpunit>
28+
```
29+
30+
And then, remove all the `use Factories;` statements from your factories.
31+
32+
## Rector rules
33+
34+
A Rector set is available to automatically remove the usage of the trait in all your tests.
35+
36+
First, you'll need to install `rector/rector`:
37+
```shell
38+
composer require --dev rector/rector
39+
```
40+
41+
Then, create a `rector.php` file:
42+
43+
```php
44+
<?php
45+
46+
use Rector\Config\RectorConfig;
47+
use Zenstruck\Foundry\Utils\Rector\FoundrySetList;
48+
49+
return RectorConfig::configure()
50+
->withPaths(['tests'])
51+
->withSets([FoundrySetList::FOUNDRY_2_9])
52+
;
53+
```

docs/index.rst

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,28 +1695,46 @@ Let's look at an example:
16951695

16961696
.. _enable-foundry-in-your-testcase:
16971697

1698-
Enable Foundry in your TestCase
1699-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1698+
Globally Enable Foundry In PHPUnit
1699+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17001700

1701-
Add the ``Factories`` trait for tests using factories:
1701+
Add Foundry's `PHPUnit Extension`_ in your `phpunit.xml` file:
17021702

1703-
::
1703+
.. configuration-block::
17041704

1705-
use App\Factory\PostFactory;
1706-
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
1707-
use Zenstruck\Foundry\Test\Factories;
1705+
.. code-block:: xml
17081706
1709-
class MyTest extends WebTestCase
1710-
{
1711-
use Factories;
1707+
<phpunit>
1708+
<extensions>
1709+
<bootstrap class="Zenstruck\Foundry\PHPUnit\FoundryExtension"/>
1710+
</extensions>
1711+
</phpunit>
1712+
1713+
.. versionadded:: 2.9
17121714

1713-
public function test_1(): void
1715+
The ability to globally enable Foundry with PHPUnit extension was introduced in Foundry 2.9 and requires at least
1716+
PHPUnit 10.
1717+
1718+
.. note::
1719+
1720+
If you're still using PHPUnit 9, Foundry can be enabled by adding the trait ``Zenstruck\Foundry\Test\Factories``
1721+
in each test::
1722+
1723+
use App\Factory\PostFactory;
1724+
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
1725+
use Zenstruck\Foundry\Test\Factories;
1726+
1727+
class MyTest extends WebTestCase
17141728
{
1715-
$post = PostFactory::createOne();
1729+
use Factories;
17161730

1717-
// ...
1731+
public function test_something(): void
1732+
{
1733+
$post = PostFactory::createOne();
1734+
1735+
// ...
1736+
}
17181737
}
1719-
}
17201738

17211739
Database Reset
17221740
~~~~~~~~~~~~~~
@@ -1869,7 +1887,7 @@ Foundry provides a mechanism to automatically refresh inside a functional test t
18691887

18701888
class MyTest extends WebTestCase
18711889
{
1872-
use Factories, ResetDatabase;
1890+
use ResetDatabase;
18731891

18741892
public function test_with_autorefresh(): void
18751893
{
@@ -2467,8 +2485,6 @@ any bundle configuration you have will not be picked up.
24672485

24682486
class MyUnitTest extends TestCase
24692487
{
2470-
use Factories;
2471-
24722488
public function some_test(): void
24732489
{
24742490
$post = PostFactory::createOne();

phpstan.neon

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ parameters:
3030
- identifier: missingType.iterableValue
3131
path: tests/
3232

33-
# We support both PHPUnit versions (this method changed in PHPUnit 10)
34-
- identifier: function.impossibleType
35-
path: src/Test/Factories.php
36-
3733
# PHPStan does not understand PHP version checks
3834
- message: '#Comparison operation "(<|>|<=|>=)" between int<80\d+, 80\d+> and 80\d+ is always (false|true).#'
3935

phpunit-deprecation-baseline.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
Foundry now leverages the native PHP lazy system to auto-refresh objects (it can be enabled with "zenstruck_foundry.enable_auto_refresh_with_lazy_objects" configuration).
1515
See https://github.com/zenstruck/foundry/blob/2.x/UPGRADE-2.7.md to upgrade.]]></issue>
1616

17-
<issue><![CDATA[Support for MySQL < 8 is deprecated and will be removed in DBAL 5 (AbstractMySQLDriver.php:75 called by AbstractDriverMiddleware.php:32, https://github.com/doctrine/dbal/pull/6343, package doctrine/dbal)]]></issue>
17+
<issue><![CDATA[Since zenstruck/foundry 2.9: Trait Zenstruck\Foundry\Test\Factories is deprecated and will be removed in Foundry 3. See https://github.com/zenstruck/foundry/blob/2.x/UPGRADE-2.9.md to upgrade.]]></issue>
18+
<issue><![CDATA[Since zenstruck/foundry 2.9: Not using Foundry's PHPUnit extension is deprecated and will throw an error in Foundry 3. See https://github.com/zenstruck/foundry/blob/2.x/UPGRADE-2.9.md to upgrade.]]></issue>
19+
1820
<issue><![CDATA[Since doctrine/mongodb-odm 2.14: Not using native lazy objects is deprecated and will be impossible in Doctrine MongoDB ODM 3.0.]]></issue>
1921
<issue><![CDATA[Since symfony/framework-bundle 7.3: Not setting the "property_info.with_constructor_extractor" option explicitly is deprecated because its default value will change in version 8.0.]]></issue>
2022
<issue><![CDATA[Since symfony/console 7.4: The "Symfony\Component\Console\Application::add()" method is deprecated and will be removed in Symfony 8.0, use "Symfony\Component\Console\Application::addCommand()" instead.]]></issue>

src/Configuration.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Zenstruck\Foundry\InMemory\InMemoryRepositoryRegistry;
2222
use Zenstruck\Foundry\Persistence\PersistedObjectsTracker;
2323
use Zenstruck\Foundry\Persistence\PersistenceManager;
24+
use Zenstruck\Foundry\PHPUnit\FoundryExtension;
2425

2526
/**
2627
* @author Kevin Bond <kevinbond@gmail.com>
@@ -117,7 +118,9 @@ public static function instance(): self
117118
throw new FoundryNotBooted();
118119
}
119120

120-
FactoriesTraitNotUsed::throwIfComingFromKernelTestCaseWithoutFactoriesTrait();
121+
if (!FoundryExtension::isEnabled()) {
122+
FactoriesTraitNotUsed::throwIfComingFromKernelTestCaseWithoutFactoriesTrait();
123+
}
121124

122125
return \is_callable(self::$instance) ? (self::$instance)() : self::$instance;
123126
}

src/Exception/FoundryNotBooted.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@
1111

1212
namespace Zenstruck\Foundry\Exception;
1313

14+
use Zenstruck\Foundry\PHPUnit\FoundryExtension;
15+
1416
/**
1517
* @author Kevin Bond <kevinbond@gmail.com>
1618
*/
1719
final class FoundryNotBooted extends \LogicException
1820
{
1921
public function __construct()
2022
{
21-
parent::__construct('Foundry is not yet booted. Ensure ZenstruckFoundryBundle is enabled. If in a test, ensure your TestCase has the Factories trait.');
23+
$message = FoundryExtension::shouldBeEnabled()
24+
? 'Foundry is not yet booted. Ensure ZenstruckFoundryBundle is enabled. If in a test, ensure Foundry\'s extension is enabled.'
25+
: 'Foundry is not yet booted. Ensure ZenstruckFoundryBundle is enabled. If in a test, ensure your TestCase has the Factories trait.';
26+
27+
parent::__construct($message);
2228
}
2329
}

src/PHPUnit/BootFoundryOnDataProviderMethodCalled.php

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the zenstruck/foundry package.
5+
*
6+
* (c) Kevin Bond <kevinbond@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Zenstruck\Foundry\PHPUnit;
13+
14+
use PHPUnit\Event;
15+
use PHPUnit\Event\Code\NoTestCaseObjectOnCallStackException;
16+
use PHPUnit\Framework\TestCase;
17+
use PHPUnit\Util\Test;
18+
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
19+
use Zenstruck\Foundry\Configuration;
20+
use Zenstruck\Foundry\Persistence\Proxy;
21+
use Zenstruck\Foundry\Test\UnitTestConfig;
22+
23+
/**
24+
* @internal
25+
* @author Nicolas PHILIPPE <nikophil@gmail.com>
26+
*/
27+
final class BootFoundryOnTestPrepared implements Event\Test\PreparedSubscriber
28+
{
29+
public function notify(Event\Test\Prepared $event): void
30+
{
31+
$test = $event->test();
32+
33+
if (!$test->isTestMethod()) {
34+
return;
35+
}
36+
37+
/** @var Event\Code\TestMethod $test */
38+
$this->bootFoundry($test->className());
39+
}
40+
41+
/**
42+
* @param class-string $className
43+
*/
44+
private function bootFoundry(string $className): void
45+
{
46+
if (!\is_subclass_of($className, TestCase::class)) {
47+
return;
48+
}
49+
50+
// unit test
51+
if (!\is_subclass_of($className, KernelTestCase::class)) {
52+
Configuration::boot(UnitTestConfig::build());
53+
54+
return;
55+
}
56+
57+
// integration test
58+
Configuration::boot(static function() use ($className): Configuration {
59+
if (!KernelTestCaseHelper::getContainerForTestClass($className)->has('.zenstruck_foundry.configuration')) {
60+
throw new \LogicException('ZenstruckFoundryBundle is not enabled. Ensure it is added to your config/bundles.php.');
61+
}
62+
63+
return KernelTestCaseHelper::getContainerForTestClass($className)->get('.zenstruck_foundry.configuration'); // @phpstan-ignore return.type
64+
});
65+
}
66+
}

src/PHPUnit/BuildStoryOnTestPrepared.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use PHPUnit\Event;
1717
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
1818
use Zenstruck\Foundry\Attribute\WithStory;
19-
use Zenstruck\Foundry\Exception\FactoriesTraitNotUsed;
2019

2120
/**
2221
* @internal
@@ -47,8 +46,6 @@ public function notify(Event\Test\Prepared $event): void
4746
throw new \InvalidArgumentException(\sprintf('The test class "%s" must extend "%s" to use the "%s" attribute.', $test->className(), KernelTestCase::class, WithStory::class));
4847
}
4948

50-
FactoriesTraitNotUsed::throwIfClassDoesNotHaveFactoriesTrait($test->className());
51-
5249
foreach ($withStoryAttributes as $withStoryAttribute) {
5350
$withStoryAttribute->newInstance()->story::load();
5451
}

0 commit comments

Comments
 (0)