zenstruck / foundry

A model factory library for creating expressive, auto-completable, on-demand dev/test fixtures with Symfony and Doctrine.
https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html
MIT License
644 stars 70 forks source link

Optionally disable persisting globally #471

Closed ndench closed 1 year ago

ndench commented 1 year ago

Foundry is a great bundle! We had a custom builder pattern we were using before, but are in the process of moving everything to Foundry.

We have some use cases where we want nothing to persist, but there currently doesn't seem to be a way to globally disable persisting (without putting ->withoutPersisting() in our AbstractFactory).

Our use cases are:

  1. Contract tests
    • Extends KernelTestCase to access services in the container (eg. the serializer)
    • Create some models and serialize them to ensure they meet the contract
    • No need to persist entities here
  2. Previewing email notifications without sending them
    • Using faker to generate fake data to instantiate different notification classes
    • Render the email notification in the browser in dev
    • Allows us to quickly iterate email design without having to trigger the email notification

Our "solution" to item 1 has been to call the internal TestState::bootFoundryForUnitTests() method in the setUp() method of our contract tests. This creates Foundry without an entity manager, so the entities aren't persisted even though we're technically in a KernelTestCase.

However, we don't have a solution for item 2. It would be great to be able to use TestState::configure() or TestState::disablePersist() at runtime before we instantiate any factories.

Has anyone else had similar use cases? Do you think this would be a valuable addition to the library?

nikophil commented 1 year ago

Hello,

This would be indeed a nice addition! Maybe we could create a method Configuration::disablePersist() and then set Factory::$persist in the factory's constructor depending on that?

but since Configuration is internal, we have to find another place where we can call Configuration::disablePersist(). Maybe a method disablePersit() in Factories trait? or a static method Factory::disablePersist()?

any thoughts @kbond?

kbond commented 1 year ago

Maybe a method disablePersit() in Factories trait?

This was my first thought, then auto-re-enable after each test?

nikophil commented 1 year ago

yep we can do this in a @after hook

kbond commented 1 year ago

or a static method Factory::disablePersist()?

I'd say let's try and keep it to the test trait for now but this could be a possibility if this functionality is required outside of tests.

nikophil commented 1 year ago

some thoughts about this: we should also throw an exception if Configuration::disablePersist() has been called, and if some method like Factory::repository() on Factory::find() is used

I'll work on this task soon, since I think it will be a nice addition!