Passed
Pull Request — master (#7448)
by Ilya
10:36
created

EntityManagerTest::testGetUnitOfWork()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\ORM;
6
7
use Doctrine\Common\EventManager;
8
use Doctrine\DBAL\Connection;
9
use Doctrine\ORM\Configuration;
10
use Doctrine\ORM\EntityManager;
11
use Doctrine\ORM\Event\PreFlushEventArgs;
12
use Doctrine\ORM\Events;
13
use Doctrine\ORM\Exception\EntityManagerClosed;
14
use Doctrine\ORM\Mapping\ClassMetadataFactory;
15
use Doctrine\ORM\Mapping\Driver\MappingDriver;
16
use Doctrine\ORM\ORMInvalidArgumentException;
17
use Doctrine\ORM\Proxy\Factory\ProxyFactory;
18
use Doctrine\ORM\Query;
19
use Doctrine\ORM\Query\ResultSetMapping;
20
use Doctrine\ORM\QueryBuilder;
21
use Doctrine\ORM\UnitOfWork;
22
use Doctrine\Tests\Models\CMS\CmsUser;
23
use Doctrine\Tests\Models\GeoNames\Country;
24
use Doctrine\Tests\Models\IdentityIsAssociation\SimpleId;
25
use Doctrine\Tests\Models\IdentityIsAssociation\ToOneAssociationIdToSimpleId;
26
use Doctrine\Tests\Models\IdentityIsAssociation\ToOneCompositeAssociationToMultipleSimpleId;
27
use Doctrine\Tests\OrmTestCase;
28
use InvalidArgumentException;
29
use stdClass;
30
use TypeError;
31
32
class EntityManagerTest extends OrmTestCase
33
{
34
    /** @var EntityManager */
35
    private $em;
36
37
    public function setUp() : void
38
    {
39
        parent::setUp();
40
41
        $this->em = $this->getTestEntityManager();
42
    }
43
44
    /**
45
     * @group DDC-899
46
     */
47
    public function testIsOpen() : void
48
    {
49
        self::assertTrue($this->em->isOpen());
50
        $this->em->close();
51
        self::assertFalse($this->em->isOpen());
52
    }
53
54
    public function testGetConnection() : void
55
    {
56
        self::assertInstanceOf(Connection::class, $this->em->getConnection());
57
    }
58
59
    public function testGetMetadataFactory() : void
60
    {
61
        self::assertInstanceOf(ClassMetadataFactory::class, $this->em->getMetadataFactory());
62
    }
63
64
    public function testGetConfiguration() : void
65
    {
66
        self::assertInstanceOf(Configuration::class, $this->em->getConfiguration());
67
    }
68
69
    public function testGetUnitOfWork() : void
70
    {
71
        self::assertInstanceOf(UnitOfWork::class, $this->em->getUnitOfWork());
72
    }
73
74
    public function testGetProxyFactory() : void
75
    {
76
        self::assertInstanceOf(ProxyFactory::class, $this->em->getProxyFactory());
77
    }
78
79
    public function testGetEventManager() : void
80
    {
81
        self::assertInstanceOf(EventManager::class, $this->em->getEventManager());
82
    }
83
84
    public function testCreateNativeQuery() : void
85
    {
86
        $rsm   = new ResultSetMapping();
87
        $query = $this->em->createNativeQuery('SELECT foo', $rsm);
88
89
        self::assertSame('SELECT foo', $query->getSql());
90
    }
91
92
    public function testCreateQueryBuilder() : void
93
    {
94
        self::assertInstanceOf(QueryBuilder::class, $this->em->createQueryBuilder());
95
    }
96
97
    public function testCreateQueryBuilderAliasValid() : void
98
    {
99
        $q  = $this->em->createQueryBuilder()
100
             ->select('u')->from(CmsUser::class, 'u');
101
        $q2 = clone $q;
102
103
        self::assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u', $q->getQuery()->getDql());
104
        self::assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u', $q2->getQuery()->getDql());
105
106
        $q3 = clone $q;
107
108
        self::assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u', $q3->getQuery()->getDql());
109
    }
110
111
    public function testCreateQueryDqlIsOptional() : void
112
    {
113
        self::assertInstanceOf(Query::class, $this->em->createQuery());
114
    }
115
116
    public function testGetPartialReference() : void
117
    {
118
        $user = $this->em->getPartialReference(CmsUser::class, 42);
119
        self::assertTrue($this->em->contains($user));
120
        self::assertEquals(42, $user->id);
121
        self::assertNull($user->getName());
122
    }
123
124
    public function testCreateQuery() : void
125
    {
126
        $q = $this->em->createQuery('SELECT 1');
127
        self::assertInstanceOf(Query::class, $q);
128
        self::assertEquals('SELECT 1', $q->getDql());
129
    }
130
131
    public static function dataMethodsAffectedByNoObjectArguments()
132
    {
133
        return [
134
            ['persist'],
135
            ['remove'],
136
            ['refresh'],
137
        ];
138
    }
139
140
    /**
141
     * @dataProvider dataMethodsAffectedByNoObjectArguments
142
     */
143
    public function testThrowsExceptionOnNonObjectValues($methodName) : void
144
    {
145
        $this->expectException(ORMInvalidArgumentException::class);
146
        $this->expectExceptionMessage('EntityManager#' . $methodName . '() expects parameter 1 to be an entity object, NULL given.');
147
148
        $this->em->{$methodName}(null);
149
    }
150
151
    public static function dataAffectedByErrorIfClosedException()
152
    {
153
        return [
154
            ['flush'],
155
            ['persist'],
156
            ['remove'],
157
            ['refresh'],
158
        ];
159
    }
160
161
    /**
162
     * @param string $methodName
163
     *
164
     * @dataProvider dataAffectedByErrorIfClosedException
165
     */
166
    public function testAffectedByErrorIfClosedException($methodName) : void
167
    {
168
        $this->expectException(EntityManagerClosed::class);
169
        $this->expectExceptionMessage('closed');
170
171
        $this->em->close();
172
        $this->em->{$methodName}(new stdClass());
173
    }
174
175
    public function dataToBeReturnedByTransactional()
176
    {
177
        return [
178
            [null],
179
            [false],
180
            ['foo'],
181
        ];
182
    }
183
184
    /**
185
     * @dataProvider dataToBeReturnedByTransactional
186
     */
187
    public function testTransactionalAcceptsReturn($value) : void
188
    {
189
        self::assertSame(
190
            $value,
191
            $this->em->transactional(static function ($em) use ($value) {
192
                return $value;
193
            })
194
        );
195
    }
196
197
    public function testTransactionalAcceptsVariousCallables() : void
198
    {
199
        self::assertSame('callback', $this->em->transactional([$this, 'transactionalCallback']));
200
    }
201
202
    public function transactionalCallback($em)
203
    {
204
        self::assertSame($this->em, $em);
205
        return 'callback';
206
    }
207
208
    public function testCreateInvalidConnection() : void
209
    {
210
        $this->expectException(InvalidArgumentException::class);
211
        $this->expectExceptionMessage('Invalid $connection argument of type integer given: "1".');
212
213
        $config = new Configuration();
214
        $config->setMetadataDriverImpl($this->createMock(MappingDriver::class));
215
        EntityManager::create(1, $config);
0 ignored issues
show
Bug introduced by
1 of type integer is incompatible with the type Doctrine\DBAL\Connection|array<mixed,mixed> expected by parameter $connection of Doctrine\ORM\EntityManager::create(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

215
        EntityManager::create(/** @scrutinizer ignore-type */ 1, $config);
Loading history...
216
    }
217
218
    /**
219
     * @group #5796
220
     */
221
    public function testTransactionalReThrowsThrowables() : void
222
    {
223
        try {
224
            $this->em->transactional(static function () {
225
                (static function (array $value) {
226
                    // this only serves as an IIFE that throws a `TypeError`
227
                })(null);
228
            });
229
230
            self::fail('TypeError expected to be thrown');
231
        } catch (TypeError $ignored) {
232
            self::assertFalse($this->em->isOpen());
233
        }
234
    }
235
236
    /**
237
     * @group 6017
238
     */
239
    public function testClearManager() : void
240
    {
241
        $entity = new Country(456, 'United Kingdom');
242
243
        $this->em->persist($entity);
244
245
        self::assertTrue($this->em->contains($entity));
246
247
        $this->em->clear();
248
249
        self::assertFalse($this->em->contains($entity));
250
    }
251
252
    public function testGetReferenceRetrievesReferencesWithGivenProxiesAsIdentifiers() : void
253
    {
254
        $simpleIdReference = $this->em->getReference(
255
            SimpleId::class,
256
            ['id' => 123]
257
        );
258
        /** @var GhostObjectInterface|ToOneAssociationIdToSimpleId $nestedReference */
259
        $nestedIdReference = $this->em->getReference(
260
            ToOneAssociationIdToSimpleId::class,
261
            ['simpleId' => $simpleIdReference]
262
        );
263
264
        self::assertInstanceOf(ToOneAssociationIdToSimpleId::class, $nestedIdReference);
265
        self::assertSame($simpleIdReference, $nestedIdReference->simpleId);
266
        self::assertTrue($this->em->contains($simpleIdReference));
267
        self::assertTrue($this->em->contains($nestedIdReference));
268
    }
269
270
    public function testGetReferenceRetrievesReferencesWithGivenProxiesAsIdentifiersEvenIfIdentifierOrderIsSwapped() : void
271
    {
272
        $simpleIdReferenceA = $this->em->getReference(
273
            SimpleId::class,
274
            ['id' => 123]
275
        );
276
        $simpleIdReferenceB = $this->em->getReference(
277
            SimpleId::class,
278
            ['id' => 456]
279
        );
280
        /** @var GhostObjectInterface|ToOneCompositeAssociationToMultipleSimpleId $nestedIdReference */
281
        $nestedIdReference = $this->em->getReference(
282
            ToOneCompositeAssociationToMultipleSimpleId::class,
283
            ['simpleIdB' => $simpleIdReferenceB, 'simpleIdA' => $simpleIdReferenceA]
284
        );
285
286
        self::assertInstanceOf(ToOneCompositeAssociationToMultipleSimpleId::class, $nestedIdReference);
287
        self::assertSame($simpleIdReferenceA, $nestedIdReference->simpleIdA);
288
        self::assertSame($simpleIdReferenceB, $nestedIdReference->simpleIdB);
289
        self::assertTrue($this->em->contains($simpleIdReferenceA));
290
        self::assertTrue($this->em->contains($simpleIdReferenceB));
291
        self::assertTrue($this->em->contains($nestedIdReference));
292
    }
293
294
    public function testCallingFlushInsideFlush()
295
    {
296
        $listener = new class($this)
297
        {
298
            /** @var OrmTestCase */
299
            private $testCase;
300
301
            public function __construct(OrmTestCase $testCase)
302
            {
303
                $this->testCase = $testCase;
304
            }
305
            /** @var bool This flag is used to prevent infinity loop in case of regression */
306
            private $alreadyInPreFlush = false;
307
308
            public function preFlush(PreFlushEventArgs $eventArgs)
309
            {
310
                if ($this->alreadyInPreFlush) {
311
                    $this->testCase->fail('Flush inside flush called. It should not happened. Fail test to prevent infinity loop');
312
                }
313
                $eventArgs->getEntityManager()->flush();
314
                $this->alreadyInPreFlush = true;
315
            }
316
        };
317
318
        $this->expectException(\LogicException::class);
0 ignored issues
show
introduced by
Class \LogicException should not be referenced via a fully qualified name, but via a use statement.
Loading history...
319
        $this->em->getEventManager()->addEventListener(Events::preFlush, $listener);
320
        $this->em->flush();
321
    }
322
}
323