Skip to content

Commit 9e3d227

Browse files
guiwodapatrickbrouwers
authored andcommitted
[FEATURE] Testing\FactoryBuilder automatic *toMany associations (#231)
* FactoryBuilder fills *toMany associations with an empty `ArrayCollection` Also, added test for FactoryBuilder's `make` and `create` methods. * Don't override definition with automatic associations.
1 parent 9a36ef7 commit 9e3d227

File tree

2 files changed

+186
-1
lines changed

2 files changed

+186
-1
lines changed

src/Testing/FactoryBuilder.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace LaravelDoctrine\ORM\Testing;
44

5+
use Doctrine\Common\Collections\ArrayCollection;
56
use Doctrine\Common\Persistence\ManagerRegistry;
7+
use Doctrine\ORM\Mapping\ClassMetadata;
68
use Faker\Generator as Faker;
79
use Illuminate\Support\Collection;
810
use InvalidArgumentException;
@@ -147,9 +149,23 @@ protected function makeInstance(array $attributes = [])
147149
return $definition;
148150
}
149151

152+
/** @var ClassMetadata $metadata */
153+
$metadata = $this->registry
154+
->getManagerForClass($this->class)
155+
->getClassMetadata($this->class);
156+
157+
$toManyRelations = (new Collection($metadata->getAssociationMappings()))
158+
->keys()
159+
->filter(function ($association) use ($metadata) {
160+
return $metadata->isCollectionValuedAssociation($association);
161+
})
162+
->mapWithKeys(function ($association) {
163+
return [$association => new ArrayCollection];
164+
});
165+
150166
return SimpleHydrator::hydrate(
151167
$this->class,
152-
$this->callClosureAttributes(array_merge($definition, $attributes))
168+
$this->callClosureAttributes(array_merge($toManyRelations->all(), $definition, $attributes))
153169
);
154170
}
155171

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
<?php
2+
3+
namespace {
4+
5+
use Doctrine\Common\Collections\ArrayCollection;
6+
use Doctrine\Common\Persistence\ManagerRegistry;
7+
use Doctrine\ORM\EntityManager;
8+
use Doctrine\ORM\EntityManagerInterface;
9+
use Doctrine\ORM\Tools\Setup;
10+
use LaravelDoctrine\ORM\Testing\FactoryBuilder;
11+
use Mockery\Adapter\Phpunit\MockeryTestCase;
12+
13+
class FactoryBuilderTest extends MockeryTestCase
14+
{
15+
/**
16+
* @var ManagerRegistry|\Mockery\Mock
17+
*/
18+
private $aRegistry;
19+
20+
/**
21+
* @var string
22+
*/
23+
private $aClass;
24+
25+
/**
26+
* @var string
27+
*/
28+
private $aName;
29+
30+
/**
31+
* @var callable[]|\Mockery\Mock[]
32+
*/
33+
private $definitions;
34+
35+
/**
36+
* @var \Faker\Generator|\Mockery\Mock
37+
*/
38+
private $faker;
39+
40+
/**
41+
* @var EntityManagerInterface|\Mockery\Mock
42+
*/
43+
private $entityManager;
44+
45+
protected function setUp()
46+
{
47+
$this->aRegistry = \Mockery::mock(ManagerRegistry::class);
48+
$this->aClass = EntityStub::class;
49+
$this->aName = 'default';
50+
$this->faker = \Mockery::mock(Faker\Generator::class);
51+
$this->definitions = [
52+
EntityStub::class => [
53+
$this->aName => function () {
54+
return [
55+
'id' => random_int(1, 9),
56+
'name' => 'A Name',
57+
];
58+
}
59+
]
60+
];
61+
62+
$this->aRegistry
63+
->shouldReceive('getManagerForClass')
64+
->with(EntityStub::class)
65+
->andReturn($this->entityManager = \Mockery::mock(EntityManagerInterface::class));
66+
67+
$classMetadata = $this->getEntityManager()->getClassMetadata(EntityStub::class);
68+
69+
$this->entityManager->shouldReceive('getClassMetadata')
70+
->with(EntityStub::class)
71+
->andReturn($classMetadata);
72+
73+
$this->entityManager->shouldReceive('persist');
74+
$this->entityManager->shouldReceive('flush');
75+
}
76+
77+
protected function getFactoryBuilder(array $definitions = []): FactoryBuilder
78+
{
79+
return new FactoryBuilder(
80+
$this->aRegistry,
81+
$this->aClass,
82+
$this->aName,
83+
array_merge($this->definitions, $definitions),
84+
$this->faker
85+
);
86+
}
87+
88+
protected function getEntityManager()
89+
{
90+
$conn = [
91+
'driver' => 'pdo_sqlite',
92+
'database' => ':memory:',
93+
];
94+
95+
$config = Setup::createAnnotationMetadataConfiguration([__DIR__], true);
96+
97+
return EntityManager::create($conn, $config);
98+
}
99+
100+
public function test_it_makes_instances_of_the_class()
101+
{
102+
$instance = $this->getFactoryBuilder()->make();
103+
104+
$this->assertInstanceOf(EntityStub::class, $instance);
105+
}
106+
107+
public function test_it_creates_instances_of_the_class()
108+
{
109+
$instance = $this->getFactoryBuilder()->create();
110+
111+
$this->entityManager->shouldHaveReceived('persist')->with($instance)->once();
112+
$this->entityManager->shouldHaveReceived('flush')->once();
113+
}
114+
115+
public function test_it_fills_to_many_relations_with_array_collections()
116+
{
117+
$instance = $this->getFactoryBuilder()->make();
118+
119+
$this->assertInstanceOf(ArrayCollection::class, $instance->others);
120+
}
121+
122+
public function test_it_shouldnt_override_predefined_relations()
123+
{
124+
$instance = $this->getFactoryBuilder([
125+
EntityStub::class => [
126+
'default' => function () {
127+
return [
128+
'id' => 1,
129+
'name' => 'a name',
130+
'others' => ['Foo'],
131+
];
132+
}
133+
]
134+
])->make();
135+
136+
$this->assertEquals(['Foo'], $instance->others);
137+
}
138+
}
139+
140+
/**
141+
* @Entity
142+
*/
143+
class EntityStub
144+
{
145+
/**
146+
* @Id @GeneratedValue @Column(type="integer")
147+
*/
148+
public $id;
149+
150+
/**
151+
* @Column(type="string")
152+
*/
153+
public $name;
154+
155+
/**
156+
* @ManyToMany(targetEntity="EntityStub")
157+
* @JoinTable(name="stub_stubs",
158+
* joinColumns={@JoinColumn(name="owner_id", referencedColumnName="id")},
159+
* inverseJoinColumns={@JoinColumn(name="owned_id", referencedColumnName="id")}
160+
* )
161+
*/
162+
public $others;
163+
}
164+
}
165+
namespace Faker {
166+
interface Generator
167+
{
168+
}
169+
}

0 commit comments

Comments
 (0)