Failed Conditions
Pull Request — master (#7796)
by
unknown
09:55
created

PersistentCollectionTest::testNonObjects()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 0
dl 0
loc 19
rs 9.9
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\Collections\ArrayCollection;
8
use Doctrine\ORM\Mapping\ChangeTrackingPolicy;
9
use Doctrine\ORM\PersistentCollection;
10
use Doctrine\ORM\UnitOfWork;
11
use Doctrine\Tests\Mocks\ConnectionMock;
12
use Doctrine\Tests\Mocks\DriverMock;
13
use Doctrine\Tests\Mocks\EntityManagerMock;
14
use Doctrine\Tests\Models\ECommerce\ECommerceCart;
15
use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
16
use Doctrine\Tests\OrmTestCase;
17
use PHPUnit_Framework_MockObject_MockObject;
18
use stdClass;
19
use function array_keys;
20
21
/**
22
 * Tests the lazy-loading capabilities of the PersistentCollection and the initialization of collections.
23
 */
24
class PersistentCollectionTest extends OrmTestCase
25
{
26
    /** @var PersistentCollection */
27
    protected $collection;
28
29
    /** @var EntityManagerMock */
30
    private $emMock;
31
32
    protected function setUp() : void
33
    {
34
        parent::setUp();
35
36
        $this->emMock = EntityManagerMock::create(new ConnectionMock([], new DriverMock()));
37
38
        $this->setUpPersistentCollection();
39
    }
40
41
    /**
42
     * Set up the PersistentCollection used for collection initialization tests.
43
     */
44
    public function setUpPersistentCollection()
45
    {
46
        $classMetaData    = $this->emMock->getClassMetadata(ECommerceCart::class);
47
        $this->collection = new PersistentCollection($this->emMock, $classMetaData, new ArrayCollection());
48
        $this->collection->setInitialized(false);
49
        $this->collection->setOwner(new ECommerceCart(), $classMetaData->getProperty('products'));
0 ignored issues
show
Bug introduced by
The method getProperty() does not exist on Doctrine\Common\Persistence\Mapping\ClassMetadata. ( Ignorable by Annotation )

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

49
        $this->collection->setOwner(new ECommerceCart(), $classMetaData->/** @scrutinizer ignore-call */ getProperty('products'));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
50
    }
51
52
    public function testCanBePutInLazyLoadingMode() : void
53
    {
54
        $class      = $this->emMock->getClassMetadata(ECommerceProduct::class);
55
        $collection = new PersistentCollection($this->emMock, $class, new ArrayCollection());
56
        $collection->setInitialized(false);
57
        self::assertFalse($collection->isInitialized());
58
    }
59
60
    /**
61
     * Test that PersistentCollection::current() initializes the collection.
62
     */
63
    public function testCurrentInitializesCollection() : void
64
    {
65
        $this->collection->current();
66
        self::assertTrue($this->collection->isInitialized());
67
    }
68
69
    /**
70
     * Test that PersistentCollection::key() initializes the collection.
71
     */
72
    public function testKeyInitializesCollection() : void
73
    {
74
        $this->collection->key();
75
        self::assertTrue($this->collection->isInitialized());
76
    }
77
78
    /**
79
     * Test that PersistentCollection::next() initializes the collection.
80
     */
81
    public function testNextInitializesCollection() : void
82
    {
83
        $this->collection->next();
84
        self::assertTrue($this->collection->isInitialized());
85
    }
86
87
    /**
88
     * @group DDC-3382
89
     */
90
    public function testNonObjects() : void
91
    {
92
        $this->setUpPersistentCollection();
93
94
        self::assertEmpty($this->collection);
95
96
        $this->collection->add('dummy');
97
98
        self::assertNotEmpty($this->collection);
99
100
        $product = new ECommerceProduct();
101
102
        $this->collection->set(1, $product);
103
        $this->collection->set(2, 'dummy');
104
        $this->collection->set(3, null);
105
106
        self::assertSame($product, $this->collection->get(1));
107
        self::assertSame('dummy', $this->collection->get(2));
108
        self::assertNull($this->collection->get(3));
109
    }
110
111
    /**
112
     * @group 6110
113
     */
114
    public function testRemovingElementsAlsoRemovesKeys() : void
115
    {
116
        $dummy = new stdClass();
117
118
        $this->setUpPersistentCollection();
119
120
        $this->collection->add($dummy);
121
        self::assertEquals([0], array_keys($this->collection->toArray()));
122
123
        $this->collection->removeElement($dummy);
124
        self::assertEquals([], array_keys($this->collection->toArray()));
125
    }
126
127
    /**
128
     * @group 6110
129
     */
130
    public function testClearWillAlsoClearKeys() : void
131
    {
132
        $this->collection->add(new stdClass());
133
        $this->collection->clear();
134
        self::assertEquals([], array_keys($this->collection->toArray()));
135
    }
136
137
    /**
138
     * @group 6110
139
     */
140
    public function testClearWillAlsoResetKeyPositions() : void
141
    {
142
        $dummy = new stdClass();
143
144
        $this->collection->add($dummy);
145
        $this->collection->removeElement($dummy);
146
        $this->collection->clear();
147
148
        $this->collection->add($dummy);
149
150
        self::assertEquals([0], array_keys($this->collection->toArray()));
151
    }
152
153
    /**
154
     * @group 6613
155
     * @group 6614
156
     * @group 6616
157
     */
158
    public function testWillKeepNewItemsInDirtyCollectionAfterInitialization() : void
159
    {
160
        /** @var UnitOfWork|PHPUnit_Framework_MockObject_MockObject $unitOfWork */
161
        $unitOfWork = $this->createMock(UnitOfWork::class);
162
163
        $this->emMock->setUnitOfWork($unitOfWork);
164
165
        $newElement       = new stdClass();
166
        $persistedElement = new stdClass();
167
168
        $this->collection->add($newElement);
169
170
        self::assertFalse($this->collection->isInitialized());
171
        self::assertTrue($this->collection->isDirty());
172
173
        $unitOfWork
174
            ->expects(self::once())
175
            ->method('loadCollection')
176
            ->with($this->collection)
177
            ->willReturnCallback(static function (PersistentCollection $persistentCollection) use ($persistedElement) : void {
178
                $persistentCollection->unwrap()->add($persistedElement);
179
            });
180
181
        $this->collection->initialize();
182
183
        self::assertSame([$persistedElement, $newElement], $this->collection->toArray());
184
        self::assertTrue($this->collection->isInitialized());
185
        self::assertTrue($this->collection->isDirty());
186
    }
187
188
    /**
189
     * @group 6613
190
     * @group 6614
191
     * @group 6616
192
     */
193
    public function testWillDeDuplicateNewItemsThatWerePreviouslyPersistedInDirtyCollectionAfterInitialization() : void
194
    {
195
        /** @var UnitOfWork|PHPUnit_Framework_MockObject_MockObject $unitOfWork */
196
        $unitOfWork = $this->createMock(UnitOfWork::class);
197
198
        $this->emMock->setUnitOfWork($unitOfWork);
199
200
        $newElement                    = new stdClass();
201
        $newElementThatIsAlsoPersisted = new stdClass();
202
        $persistedElement              = new stdClass();
203
204
        $this->collection->add($newElementThatIsAlsoPersisted);
205
        $this->collection->add($newElement);
206
207
        self::assertFalse($this->collection->isInitialized());
208
        self::assertTrue($this->collection->isDirty());
209
210
        $unitOfWork
211
            ->expects(self::once())
212
            ->method('loadCollection')
213
            ->with($this->collection)
214
            ->willReturnCallback(static function (PersistentCollection $persistentCollection) use (
215
                $persistedElement,
216
                $newElementThatIsAlsoPersisted
217
            ) : void {
218
                $persistentCollection->unwrap()->add($newElementThatIsAlsoPersisted);
219
                $persistentCollection->unwrap()->add($persistedElement);
220
            });
221
222
        $this->collection->initialize();
223
224
        self::assertSame(
225
            [$newElementThatIsAlsoPersisted, $persistedElement, $newElement],
226
            $this->collection->toArray()
227
        );
228
        self::assertTrue($this->collection->isInitialized());
229
        self::assertTrue($this->collection->isDirty());
230
    }
231
232
    /**
233
     * @group 6613
234
     * @group 6614
235
     * @group 6616
236
     */
237
    public function testWillNotMarkCollectionAsDirtyAfterInitializationIfNoElementsWereAdded() : void
238
    {
239
        /** @var UnitOfWork|PHPUnit_Framework_MockObject_MockObject $unitOfWork */
240
        $unitOfWork = $this->createMock(UnitOfWork::class);
241
242
        $this->emMock->setUnitOfWork($unitOfWork);
243
244
        $newElementThatIsAlsoPersisted = new stdClass();
245
        $persistedElement              = new stdClass();
246
247
        $this->collection->add($newElementThatIsAlsoPersisted);
248
249
        self::assertFalse($this->collection->isInitialized());
250
        self::assertTrue($this->collection->isDirty());
251
252
        $unitOfWork
253
            ->expects(self::once())
254
            ->method('loadCollection')
255
            ->with($this->collection)
256
            ->willReturnCallback(static function (PersistentCollection $persistentCollection) use (
257
                $persistedElement,
258
                $newElementThatIsAlsoPersisted
259
            ) : void {
260
                $persistentCollection->unwrap()->add($newElementThatIsAlsoPersisted);
261
                $persistentCollection->unwrap()->add($persistedElement);
262
            });
263
264
        $this->collection->initialize();
265
266
        self::assertSame(
267
            [$newElementThatIsAlsoPersisted, $persistedElement],
268
            $this->collection->toArray()
269
        );
270
        self::assertTrue($this->collection->isInitialized());
271
        self::assertFalse($this->collection->isDirty());
272
    }
273
274
    public function testModifyUOWForDeferredImplicitOwnerOnClear() : void
275
    {
276
        $unitOfWork = $this->createMock(UnitOfWork::class);
277
        $unitOfWork->expects(self::once())->method('scheduleCollectionDeletion');
278
        $this->emMock->setUnitOfWork($unitOfWork);
279
280
        $this->collection->clear();
281
    }
282
283
    public function testDoNotModifyUOWForDeferredExplicitOwnerOnClear() : void
284
    {
285
        $unitOfWork = $this->createMock(UnitOfWork::class);
286
        $unitOfWork->expects(self::never())->method('scheduleCollectionDeletion');
287
        $this->emMock->setUnitOfWork($unitOfWork);
288
289
        $classMetaData = $this->emMock->getClassMetadata(ECommerceCart::class);
290
        $classMetaData->setChangeTrackingPolicy(ChangeTrackingPolicy::DEFERRED_EXPLICIT);
0 ignored issues
show
Bug introduced by
The method setChangeTrackingPolicy() does not exist on Doctrine\Common\Persistence\Mapping\ClassMetadata. ( Ignorable by Annotation )

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

290
        $classMetaData->/** @scrutinizer ignore-call */ 
291
                        setChangeTrackingPolicy(ChangeTrackingPolicy::DEFERRED_EXPLICIT);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
291
292
        $this->collection->clear();
293
    }
294
}
295