Passed
Pull Request — master (#7448)
by Ilya
14:31
created

EntityManagerTest::testIsOpen()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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

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