From ebc20a2068ac0c558ddaf8ce605537b55ed1ff7c Mon Sep 17 00:00:00 2001 From: Guido Contreras Woda Date: Mon, 24 Apr 2017 15:43:41 -0300 Subject: [PATCH 1/2] FactoryBuilder fills *toMany associations with an empty `ArrayCollection` Also, added test for FactoryBuilder's `make` and `create` methods. --- src/Testing/FactoryBuilder.php | 18 +++- tests/Testing/FactoryBuilderTest.php | 151 +++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 tests/Testing/FactoryBuilderTest.php diff --git a/src/Testing/FactoryBuilder.php b/src/Testing/FactoryBuilder.php index bd1a05c0..83d872a2 100644 --- a/src/Testing/FactoryBuilder.php +++ b/src/Testing/FactoryBuilder.php @@ -2,7 +2,9 @@ namespace LaravelDoctrine\ORM\Testing; +use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Persistence\ManagerRegistry; +use Doctrine\ORM\Mapping\ClassMetadata; use Faker\Generator as Faker; use Illuminate\Support\Collection; use InvalidArgumentException; @@ -147,9 +149,23 @@ protected function makeInstance(array $attributes = []) return $definition; } + /** @var ClassMetadata $metadata */ + $metadata = $this->registry + ->getManagerForClass($this->class) + ->getClassMetadata($this->class); + + $toManyRelations = (new Collection($metadata->getAssociationMappings())) + ->keys() + ->filter(function ($association) use ($metadata) { + return $metadata->isCollectionValuedAssociation($association); + }) + ->mapWithKeys(function ($association) { + return [$association => new ArrayCollection]; + }); + return SimpleHydrator::hydrate( $this->class, - $this->callClosureAttributes(array_merge($definition, $attributes)) + $this->callClosureAttributes(array_merge($definition, $toManyRelations->all(), $attributes)) ); } diff --git a/tests/Testing/FactoryBuilderTest.php b/tests/Testing/FactoryBuilderTest.php new file mode 100644 index 00000000..68fad8ef --- /dev/null +++ b/tests/Testing/FactoryBuilderTest.php @@ -0,0 +1,151 @@ +aRegistry = \Mockery::mock(ManagerRegistry::class); + $this->aClass = EntityStub::class; + $this->aName = 'default'; + $this->faker = \Mockery::mock(Faker\Generator::class); + $this->definitions = [ + EntityStub::class => [ + $this->aName => function () { + return [ + 'id' => random_int(1, 9), + 'name' => 'A Name', + ]; + } + ] + ]; + + $this->aRegistry + ->shouldReceive('getManagerForClass') + ->with(EntityStub::class) + ->andReturn($this->entityManager = \Mockery::mock(EntityManagerInterface::class)); + + $classMetadata = $this->getEntityManager()->getClassMetadata(EntityStub::class); + + $this->entityManager->shouldReceive('getClassMetadata') + ->with(EntityStub::class) + ->andReturn($classMetadata); + + $this->entityManager->shouldReceive('persist'); + $this->entityManager->shouldReceive('flush'); + + } + + protected function getFactoryBuilder(array $definitions = []): FactoryBuilder + { + return new FactoryBuilder( + $this->aRegistry, + $this->aClass, + $this->aName, + array_merge($this->definitions, $definitions), + $this->faker + ); + } + + protected function getEntityManager() + { + $conn = [ + 'driver' => 'pdo_sqlite', + 'database' => ':memory:', + ]; + + $config = Setup::createAnnotationMetadataConfiguration([__DIR__], true); + + return EntityManager::create($conn, $config); + } + + public function test_it_makes_instances_of_the_class() + { + $instance = $this->getFactoryBuilder()->make(); + + $this->assertInstanceOf(EntityStub::class, $instance); + } + + public function test_it_creates_instances_of_the_class() + { + $instance = $this->getFactoryBuilder()->create(); + + $this->entityManager->shouldHaveReceived('persist')->with($instance)->once(); + $this->entityManager->shouldHaveReceived('flush')->once(); + } + + public function test_it_fills_to_many_relations_with_array_collections() + { + $instance = $this->getFactoryBuilder()->make(); + + $this->assertInstanceOf(ArrayCollection::class, $instance->others); + } + } + + /** + * @Entity + */ + class EntityStub + { + /** + * @Id @GeneratedValue @Column(type="integer") + */ + public $id; + + /** + * @Column(type="string") + */ + public $name; + + /** + * @ManyToMany(targetEntity="EntityStub") + * @JoinTable(name="stub_stubs", + * joinColumns={@JoinColumn(name="owner_id", referencedColumnName="id")}, + * inverseJoinColumns={@JoinColumn(name="owned_id", referencedColumnName="id")} + * ) + */ + public $others; + } +} +namespace Faker { + interface Generator {} +} From 4c9613e52463e82b2147f652269b6dcfa42a3a69 Mon Sep 17 00:00:00 2001 From: Guido Contreras Woda Date: Mon, 24 Apr 2017 15:49:59 -0300 Subject: [PATCH 2/2] Don't override definition with automatic associations. --- src/Testing/FactoryBuilder.php | 2 +- tests/Testing/FactoryBuilderTest.php | 34 +++++++++++++++++++++------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/Testing/FactoryBuilder.php b/src/Testing/FactoryBuilder.php index 83d872a2..319c17ae 100644 --- a/src/Testing/FactoryBuilder.php +++ b/src/Testing/FactoryBuilder.php @@ -165,7 +165,7 @@ protected function makeInstance(array $attributes = []) return SimpleHydrator::hydrate( $this->class, - $this->callClosureAttributes(array_merge($definition, $toManyRelations->all(), $attributes)) + $this->callClosureAttributes(array_merge($toManyRelations->all(), $definition, $attributes)) ); } diff --git a/tests/Testing/FactoryBuilderTest.php b/tests/Testing/FactoryBuilderTest.php index 68fad8ef..71a16573 100644 --- a/tests/Testing/FactoryBuilderTest.php +++ b/tests/Testing/FactoryBuilderTest.php @@ -44,15 +44,15 @@ class FactoryBuilderTest extends MockeryTestCase protected function setUp() { - $this->aRegistry = \Mockery::mock(ManagerRegistry::class); - $this->aClass = EntityStub::class; - $this->aName = 'default'; - $this->faker = \Mockery::mock(Faker\Generator::class); + $this->aRegistry = \Mockery::mock(ManagerRegistry::class); + $this->aClass = EntityStub::class; + $this->aName = 'default'; + $this->faker = \Mockery::mock(Faker\Generator::class); $this->definitions = [ EntityStub::class => [ $this->aName => function () { return [ - 'id' => random_int(1, 9), + 'id' => random_int(1, 9), 'name' => 'A Name', ]; } @@ -72,7 +72,6 @@ protected function setUp() $this->entityManager->shouldReceive('persist'); $this->entityManager->shouldReceive('flush'); - } protected function getFactoryBuilder(array $definitions = []): FactoryBuilder @@ -89,7 +88,7 @@ protected function getFactoryBuilder(array $definitions = []): FactoryBuilder protected function getEntityManager() { $conn = [ - 'driver' => 'pdo_sqlite', + 'driver' => 'pdo_sqlite', 'database' => ':memory:', ]; @@ -119,6 +118,23 @@ public function test_it_fills_to_many_relations_with_array_collections() $this->assertInstanceOf(ArrayCollection::class, $instance->others); } + + public function test_it_shouldnt_override_predefined_relations() + { + $instance = $this->getFactoryBuilder([ + EntityStub::class => [ + 'default' => function () { + return [ + 'id' => 1, + 'name' => 'a name', + 'others' => ['Foo'], + ]; + } + ] + ])->make(); + + $this->assertEquals(['Foo'], $instance->others); + } } /** @@ -147,5 +163,7 @@ class EntityStub } } namespace Faker { - interface Generator {} + interface Generator + { + } }