Skip to content

Commit

Permalink
docs: using factories in data providers (#707)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikophil authored Oct 24, 2024
1 parent 470d927 commit a549c10
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 7 deletions.
63 changes: 62 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1607,7 +1607,68 @@ PHPUnit Data Providers
~~~~~~~~~~~~~~~~~~~~~~

It is possible to use factories in
`PHPUnit data providers <https://phpunit.readthedocs.io/en/9.3/writing-tests-for-phpunit.html#data-providers>`_:
`PHPUnit data providers <https://phpunit.readthedocs.io/en/9.3/writing-tests-for-phpunit.html#data-providers>`_.
Their usage depends on which Foundry version you are running:

Data Providers with Foundry ^2.2
................................

From version 2.2, Foundry provides an extension for PHPUnit.
You can install it by modifying you ``phpunit.xml.dist``:

.. configuration-block::

.. code-block:: xml
<phpunit>
<extensions>
<bootstrap class="Zenstruck\Foundry\PHPUnit\FoundryExtension"/>
</extensions>
</phpunit>

.. warning::

This PHPUnit extension requires at least PHPUnit 11.4.

Using this extension will allow to use your factories in your data providers the same way you're using them in tests.
Thanks to it, you can:
* Call ``->create()`` or ``::createOne()`` or any other method which creates objects in unit tests
(using ``PHPUnit\Framework\TestCase``) and functional tests (``Symfony\Bundle\FrameworkBundle\Test\KernelTestCase``)
* Use `Factories as Services`_ in functional tests
* Use `faker()` normally, without wrapping its call in a callable

::

use App\Factory\PostFactory;
use PHPUnit\Framework\Attributes\DataProvider;

#[DataProvider('createMultipleObjectsInDataProvider')]
public function test_post_via_data_provider(Post $post): void
{
// at this point, `$post` exists, and is already stored in database
}

public static function postDataProvider(): iterable
{
yield [PostFactory::createOne()];
yield [PostWithServiceFactory::createOne()];
yield [PostFactory::createOne(['body' => faker()->sentence()];
}
.. warning::

Because Foundry is relying on its `Proxy mechanism <object-proxy>`_, when using persistence,
your factories must extend ``Zenstruck\Foundry\Persistence\PersistentProxyObjectFactory`` to work in your data providers.

.. warning::

For the same reason, you should not call methods from `Proxy` class in your data providers,
not even ``->_real()``.


Data Providers before Foundry v2.2
..................................

::

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
use Zenstruck\Foundry\Tests\Fixture\Factories\Object1Factory;
use Zenstruck\Foundry\Tests\Fixture\Object1;

use function Zenstruck\Foundry\faker;

/**
* @author Nicolas PHILIPPE <[email protected]>
* @requires PHPUnit 11.4
Expand All @@ -34,23 +36,21 @@ final class DataProviderForServiceFactoryInKernelTestCaseTest extends KernelTest
{
use Factories;

/**
* @test
*/
#[Test]
#[DataProvider('createObjectFromServiceFactoryInDataProvider')]
public function it_can_create_one_object_in_data_provider(?Object1 $providedData): void
public function it_can_create_one_object_in_data_provider(?Object1 $providedData, string $expected): void
{
self::assertFalse(Configuration::instance()->inADataProvider());

self::assertInstanceOf(Object1::class, $providedData);
$this->assertSame('router-constructor', $providedData->getProp1());
$this->assertSame($expected, $providedData->getProp1());
}

public static function createObjectFromServiceFactoryInDataProvider(): iterable
{
yield 'service factory' => [
Object1Factory::createOne(),
Object1Factory::createOne(['prop1' => $prop1 = faker()->sentence()]),
"$prop1-constructor"
];
}
}
14 changes: 14 additions & 0 deletions tests/Integration/DataProvider/DataProviderInUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Zenstruck\Foundry\Tests\Fixture\Object1;
use Zenstruck\Foundry\Tests\Fixture\Object2;

use function Zenstruck\Foundry\faker;
use function Zenstruck\Foundry\Persistence\unproxy;

/**
Expand Down Expand Up @@ -65,4 +66,17 @@ public static function createObjectWithPersistentObjectFactoryInDataProvider():
yield 'persistent factory' => [GenericEntityFactory::createOne(), new GenericEntity('default1')];
yield 'proxy persistent factory' => [GenericProxyEntityFactory::createOne(), new GenericEntity('default1')];
}

#[Test]
#[DataProvider('createObjectUsingFakerInDataProvider')]
public function assert_it_can_create_use_faker_in_data_provider(mixed $providedData, string $expected): void
{
self::assertSame($expected, $providedData->getProp1());
}

public static function createObjectUsingFakerInDataProvider(): iterable
{
yield 'object factory' => [Object1Factory::createOne(['prop1' => $prop1 = faker()->sentence()]), "$prop1-constructor"];
yield 'persistent factory' => [GenericEntityFactory::createOne(['prop1' => $prop1 = faker()->sentence()]), $prop1];
}
}

0 comments on commit a549c10

Please sign in to comment.