Merge "[BUGFIX] Adjust unit tests to changes"
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / Persistence / RepositoryTest.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010 Bastian Waidelich <bastian@typo3.org>
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25 class Tx_Extbase_Tests_Unit_Persistence_RepositoryTest extends Tx_Extbase_Tests_Unit_BaseTestCase {
26
27 /**
28 * @var Tx_Extbase_Persistence_Repository
29 */
30 protected $repository;
31
32 /**
33 * @var Tx_Extbase_Object_ObjectManagerInterface
34 */
35 protected $mockObjectManager;
36
37 /**
38 * @var Tx_Extbase_Persistence_IdentityMap
39 */
40 protected $mockIdentityMap;
41
42 /**
43 * @var Tx_Extbase_Persistence_QueryFactory
44 */
45 protected $mockQueryFactory;
46
47 /**
48 * @var Tx_Extbase_Persistence_ManagerInterface
49 */
50 protected $mockPersistenceManager;
51
52 /**
53 * @var Tx_Extbase_Persistence_QueryInterface
54 */
55 protected $mockQuery;
56
57 /**
58 * @var Tx_Extbase_Persistence_QuerySettingsInterface
59 */
60 protected $querySettings;
61
62 public function setUp() {
63 $this->mockIdentityMap = $this->getMock('Tx_Extbase_Persistence_IdentityMap');
64 $this->mockQueryFactory = $this->getMock('Tx_Extbase_Persistence_QueryFactory');
65 $this->mockQuery = $this->getMock('Tx_Extbase_Persistence_QueryInterface');
66 $this->mockQuerySettings = $this->getMock('Tx_Extbase_Persistence_QuerySettingsInterface');
67 $this->mockQuery->expects($this->any())->method('getQuerySettings')->will($this->returnValue($this->mockQuerySettings));
68 $this->mockQueryFactory->expects($this->any())->method('create')->will($this->returnValue($this->mockQuery));
69 $this->mockPersistenceManager = $this->getMock('Tx_Extbase_Persistence_ManagerInterface');
70 $this->mockObjectManager = $this->getMock('Tx_Extbase_Object_ObjectManagerInterface');
71 $this->repository = $this->getAccessibleMock('Tx_Extbase_Persistence_Repository', array('dummy'), array($this->mockObjectManager));
72 $this->repository->injectIdentityMap($this->mockIdentityMap);
73 $this->repository->injectQueryFactory($this->mockQueryFactory);
74 $this->repository->injectPersistenceManager($this->mockPersistenceManager);
75 }
76
77 /**
78 * @test
79 */
80 public function abstractRepositoryImplementsRepositoryInterface() {
81 $this->assertTrue($this->repository instanceof Tx_Extbase_Persistence_RepositoryInterface);
82 }
83
84 /**
85 * @test
86 */
87 public function addActuallyAddsAnObjectToTheInternalObjectsArray() {
88 $someObject = new stdClass();
89
90 $this->repository->_set('objectType', get_class($someObject));
91 $this->repository->add($someObject);
92
93 $this->assertTrue($this->repository->getAddedObjects()->contains($someObject));
94 }
95
96 /**
97 * @test
98 */
99 public function removeActuallyRemovesAnObjectFromTheInternalObjectsArray() {
100 $object1 = $this->getMock('Tx_Extbase_DomainObject_AbstractDomainObject');
101 $object2 = $this->getMock('Tx_Extbase_DomainObject_AbstractDomainObject');
102 $object3 = $this->getMock('Tx_Extbase_DomainObject_AbstractDomainObject');
103
104 $this->repository->_set('objectType', get_class($object1));
105 $this->repository->add($object1);
106 $this->repository->add($object2);
107 $this->repository->add($object3);
108
109 $this->repository->remove($object2);
110
111 $this->assertTrue($this->repository->getAddedObjects()->contains($object1));
112 $this->assertFalse($this->repository->getAddedObjects()->contains($object2));
113 $this->assertTrue($this->repository->getAddedObjects()->contains($object3));
114 }
115
116 /**
117 * @test
118 */
119 public function removeRemovesTheRightObjectEvenIfItHasBeenModifiedSinceItsAddition() {
120 $object1 = $this->getMock('Tx_Extbase_DomainObject_AbstractDomainObject');
121 $object2 = $this->getMock('Tx_Extbase_DomainObject_AbstractDomainObject');
122 $object3 = $this->getMock('Tx_Extbase_DomainObject_AbstractDomainObject');
123
124 $this->repository->_set('objectType', get_class($object1));
125 $this->repository->add($object1);
126 $this->repository->add($object2);
127 $this->repository->add($object3);
128
129 $object2->setPid(1);
130 $object3->setPid(2);
131
132 $this->repository->remove($object2);
133
134 $this->assertTrue($this->repository->getAddedObjects()->contains($object1));
135 $this->assertFalse($this->repository->getAddedObjects()->contains($object2));
136 $this->assertTrue($this->repository->getAddedObjects()->contains($object3));
137 }
138
139 /**
140 * Make sure we remember the objects that are not currently add()ed
141 * but might be in persistent storage.
142 *
143 * @test
144 */
145 public function removeRetainsObjectForObjectsNotInCurrentSession() {
146 $object = $this->getMock('Tx_Extbase_DomainObject_AbstractDomainObject');
147 // if the object is not currently add()ed, it is not new
148 $object->expects($this->once())->method('_isNew')->will($this->returnValue(FALSE));
149
150 $this->repository->_set('objectType', get_class($object));
151 $this->repository->remove($object);
152
153 $this->assertTrue($this->repository->getRemovedObjects()->contains($object));
154 }
155
156 /**
157 * dataProvider for createQueryCallsQueryFactoryWithExpectedType
158 */
159 public function modelAndRepositoryClassNames() {
160 return array(
161 array('Tx_BlogExample_Domain_Repository_BlogRepository', 'Tx_BlogExample_Domain_Model_Blog'),
162 array('_Domain_Repository_Content_PageRepository', '_Domain_Model_Content_Page')
163 );
164 }
165
166 /**
167 * @test
168 * @dataProvider modelAndRepositoryClassNames
169 */
170 public function constructSetsObjectTypeFromClassName($repositoryClassName, $modelClassName) {
171 $mockClassName = 'MockRepository' . uniqid();
172 eval('class ' . $mockClassName . ' extends Tx_Extbase_Persistence_Repository {
173 protected function getRepositoryClassName() {
174 return \'' . $repositoryClassName . '\';
175 }
176 public function _getObjectType() {
177 return $this->objectType;
178 }
179 }');
180
181 $this->repository = new $mockClassName($this->mockObjectManager);
182 $this->assertEquals($modelClassName, $this->repository->_getObjectType());
183 }
184
185 /**
186 * @test
187 */
188 public function createQueryCallsQueryFactoryWithExpectedClassName() {
189 $this->mockQueryFactory->expects($this->once())->method('create')->with('ExpectedType');
190 $this->repository->_set('objectType', 'ExpectedType');
191 $this->repository->createQuery();
192 }
193
194 /**
195 * @test
196 */
197 public function createQueryReturnsQueryWithUnmodifiedDefaultQuerySettings() {
198 $mockQueryFactory = $this->getMock('Tx_Extbase_Persistence_QueryFactory');
199 $mockQuery = new Tx_Extbase_Persistence_Query('foo');
200
201 $mockDefaultQuerySettings = $this->getMock('Tx_Extbase_Persistence_QuerySettingsInterface');
202 $this->repository->injectQueryFactory($mockQueryFactory);
203 $this->repository->setDefaultQuerySettings($mockDefaultQuerySettings);
204
205 $mockQueryFactory->expects($this->once())->method('create')->will($this->returnValue($mockQuery));
206 $this->repository->createQuery();
207
208 $instanceQuerySettings = $mockQuery->getQuerySettings();
209 $this->assertEquals($mockDefaultQuerySettings, $instanceQuerySettings);
210 $this->assertNotSame($mockDefaultQuerySettings, $instanceQuerySettings);
211 }
212
213 /**
214 * @test
215 */
216 public function findAllCreatesQueryAndReturnsResultOfExecuteCall() {
217 $expectedResult = $this->getMock('Tx_Extbase_Persistence_QueryResultInterface');
218 $this->mockQuery->expects($this->once())->method('execute')->with()->will($this->returnValue($expectedResult));
219 $this->assertSame($expectedResult, $this->repository->findAll());
220 }
221
222 /**
223 * @test
224 */
225 public function findByUidReturnsResultOfGetObjectByIdentifierCall() {
226 $fakeUid = '123';
227 $object = new stdClass();
228 $this->repository->_set('objectType', 'someObjectType');
229
230 $this->mockIdentityMap->expects($this->once())->method('hasIdentifier')->with($fakeUid, 'someObjectType')->will($this->returnValue(TRUE));
231 $this->mockIdentityMap->expects($this->once())->method('getObjectByIdentifier')->with($fakeUid)->will($this->returnValue($object));
232
233 $expectedResult = $object;
234 $actualResult = $this->repository->findByUid($fakeUid);
235 $this->assertSame($expectedResult, $actualResult);
236 }
237
238 /**
239 * Replacing a reconstituted object (which has a uuid) by a new object
240 * will ask the persistence backend to replace them accordingly in the
241 * identity map.
242 *
243 * @test
244 * @return void
245 */
246 public function replaceReplacesReconstitutedEntityByNewObject() {
247 $existingObject = $this->getMock('Tx_Extbase_DomainObject_DomainObjectInterface');
248 $newObject = $this->getMock('Tx_Extbase_DomainObject_DomainObjectInterface');
249
250 $mockBackend = $this->getMock('Tx_Extbase_Persistence_BackendInterface');
251 $this->mockPersistenceManager->expects($this->once())->method('getBackend')->will($this->returnValue($mockBackend));
252 $mockBackend->expects($this->once())->method('getIdentifierByObject')->with($existingObject)->will($this->returnValue('123'));
253 $mockBackend->expects($this->once())->method('replaceObject')->with($existingObject, $newObject);
254
255 $mockSession = $this->getMock('Tx_Extbase_Persistence_Session');
256 $this->mockPersistenceManager->expects($this->once())->method('getSession')->will($this->returnValue($mockSession));
257
258 $this->repository->_set('objectType', get_class($newObject));
259 $this->repository->replace($existingObject, $newObject);
260 }
261
262 /**
263 * Replacing a reconstituted object which during this session has been
264 * marked for removal (by calling the repository's remove method)
265 * additionally registers the "newObject" for removal and removes the
266 * "existingObject" from the list of removed objects.
267 *
268 * @test
269 * @return void
270 */
271 public function replaceRemovesReconstitutedObjectWhichIsMarkedToBeRemoved() {
272 $existingObject = $this->getMock('Tx_Extbase_DomainObject_DomainObjectInterface');
273 $newObject = $this->getMock('Tx_Extbase_DomainObject_DomainObjectInterface');
274
275 $removedObjects = new SplObjectStorage;
276 $removedObjects->attach($existingObject);
277
278 $mockBackend = $this->getMock('Tx_Extbase_Persistence_BackendInterface');
279 $this->mockPersistenceManager->expects($this->once())->method('getBackend')->will($this->returnValue($mockBackend));
280 $mockBackend->expects($this->once())->method('getIdentifierByObject')->with($existingObject)->will($this->returnValue('123'));
281 $mockBackend->expects($this->once())->method('replaceObject')->with($existingObject, $newObject);
282
283 $mockSession = $this->getMock('Tx_Extbase_Persistence_Session');
284 $this->mockPersistenceManager->expects($this->once())->method('getSession')->will($this->returnValue($mockSession));
285
286 $this->repository->_set('objectType', get_class($newObject));
287 $this->repository->_set('removedObjects', $removedObjects);
288 $this->repository->replace($existingObject, $newObject);
289
290 $this->assertFalse($removedObjects->contains($existingObject));
291 $this->assertTrue($removedObjects->contains($newObject));
292 }
293
294 /**
295 * Replacing a new object which has not yet been persisted by another
296 * new object will just replace them in the repository's list of added
297 * objects.
298 *
299 * @test
300 * @return void
301 */
302 public function replaceAddsNewObjectToAddedObjects() {
303 $existingObject = $this->getMock('Tx_Extbase_DomainObject_DomainObjectInterface');
304 $newObject = $this->getMock('Tx_Extbase_DomainObject_DomainObjectInterface');
305
306 $addedObjects = new SplObjectStorage;
307 $addedObjects->attach($existingObject);
308
309 $mockBackend = $this->getMock('Tx_Extbase_Persistence_BackendInterface');
310 $this->mockPersistenceManager->expects($this->once())->method('getBackend')->will($this->returnValue($mockBackend));
311 $mockBackend->expects($this->once())->method('getIdentifierByObject')->with($existingObject)->will($this->returnValue(NULL));
312 $mockBackend->expects($this->never())->method('replaceObject');
313
314 $mockSession = $this->getMock('Tx_Extbase_Persistence_Session');
315 $this->mockPersistenceManager->expects($this->once())->method('getSession')->will($this->returnValue($mockSession));
316
317 $this->repository->_set('objectType', get_class($newObject));
318 $this->repository->_set('addedObjects', $addedObjects);
319 $this->repository->replace($existingObject, $newObject);
320
321 $this->assertFalse($addedObjects->contains($existingObject));
322 $this->assertTrue($addedObjects->contains($newObject));
323 }
324
325 /**
326 * @test
327 * @expectedException Tx_Extbase_Persistence_Exception_IllegalObjectType
328 */
329 public function replaceChecksObjectType() {
330 $this->repository->_set('objectType', 'ExpectedObjectType');
331
332 $this->repository->replace(new stdClass(), new stdClass());
333 }
334
335 /**
336 * @test
337 */
338 public function updateReplacesAnObjectWithTheSameUuidByTheGivenObject() {
339 $existingObject = new stdClass;
340 $modifiedObject = $this->getMock('Tx_Extbase_DomainObject_DomainObjectInterface');
341 $modifiedObject->expects($this->once())->method('getUid')->will($this->returnValue('123'));
342
343 $repository = $this->getAccessibleMock('Tx_Extbase_Persistence_Repository', array('findByUid', 'replace'), array($this->mockObjectManager));
344 $repository->expects($this->once())->method('findByUid')->with('123')->will($this->returnValue($existingObject));
345 $repository->expects($this->once())->method('replace')->with($existingObject, $modifiedObject);
346 $repository->_set('objectType', get_class($modifiedObject));
347 $repository->update($modifiedObject);
348 }
349
350 /**
351 * @test
352 * @expectedException Tx_Extbase_Persistence_Exception_UnknownObject
353 */
354 public function updateRejectsUnknownObjects() {
355 $someObject = $this->getMock('Tx_Extbase_DomainObject_DomainObjectInterface');
356 $someObject->expects($this->once())->method('getUid')->will($this->returnValue(NULL));
357
358 $this->repository->_set('objectType', get_class($someObject));
359
360 $this->repository->update($someObject);
361 }
362
363 /**
364 * @test
365 * @expectedException Tx_Extbase_Persistence_Exception_IllegalObjectType
366 */
367 public function updateRejectsObjectsOfWrongType() {
368 $this->repository->_set('objectType', 'Foo');
369 $this->repository->update(new stdClass());
370 }
371
372 /**
373 * @test
374 */
375 public function magicCallMethodAcceptsFindBySomethingCallsAndExecutesAQueryWithThatCriteria() {
376 $mockQueryResult = $this->getMock('Tx_Extbase_Persistence_QueryResultInterface');
377 $this->mockQuery->expects($this->once())->method('equals')->with('foo', 'bar')->will($this->returnValue('matchCriteria'));
378 $this->mockQuery->expects($this->once())->method('matching')->with('matchCriteria')->will($this->returnValue($this->mockQuery));
379 $this->mockQuery->expects($this->once())->method('execute')->will($this->returnValue($mockQueryResult));
380
381 $this->assertSame($mockQueryResult, $this->repository->findByFoo('bar'));
382 }
383
384 /**
385 * @test
386 */
387 public function magicCallMethodAcceptsFindOneBySomethingCallsAndExecutesAQueryWithThatCriteria() {
388 $object = new stdClass();
389 $mockQueryResult = $this->getMock('Tx_Extbase_Persistence_QueryResultInterface');
390 $mockQueryResult->expects($this->once())->method('getFirst')->will($this->returnValue($object));
391 $this->mockQuery->expects($this->once())->method('equals')->with('foo', 'bar')->will($this->returnValue('matchCriteria'));
392 $this->mockQuery->expects($this->once())->method('matching')->with('matchCriteria')->will($this->returnValue($this->mockQuery));
393 $this->mockQuery->expects($this->once())->method('setLimit')->with(1)->will($this->returnValue($this->mockQuery));
394 $this->mockQuery->expects($this->once())->method('execute')->will($this->returnValue($mockQueryResult));
395
396 $this->assertSame($object, $this->repository->findOneByFoo('bar'));
397 }
398
399 /**
400 * @test
401 */
402 public function magicCallMethodAcceptsCountBySomethingCallsAndExecutesAQueryWithThatCriteria() {
403 $mockQueryResult = $this->getMock('Tx_Extbase_Persistence_QueryResultInterface');
404 $mockQueryResult->expects($this->once())->method('count')->will($this->returnValue(2));
405 $this->mockQuery->expects($this->once())->method('equals')->with('foo', 'bar')->will($this->returnValue('matchCriteria'));
406 $this->mockQuery->expects($this->once())->method('matching')->with('matchCriteria')->will($this->returnValue($this->mockQuery));
407 $this->mockQuery->expects($this->once())->method('execute')->will($this->returnValue($mockQueryResult));
408
409 $this->assertSame(2, $this->repository->countByFoo('bar'));
410 }
411
412 /**
413 * @test
414 * @expectedException Exception
415 */
416 public function magicCallMethodTriggersAnErrorIfUnknownMethodsAreCalled() {
417 $this->repository->__call('foo', array());
418 }
419
420 /**
421 * @test
422 * @expectedException Tx_Extbase_Persistence_Exception_IllegalObjectType
423 */
424 public function addChecksObjectType() {
425 $this->repository->_set('objectType', 'ExpectedObjectType');
426
427 $this->repository->add(new stdClass());
428 }
429
430 /**
431 * @test
432 * @expectedException Tx_Extbase_Persistence_Exception_IllegalObjectType
433 */
434 public function removeChecksObjectType() {
435 $this->repository->_set('objectType', 'ExpectedObjectType');
436
437 $this->repository->remove(new stdClass());
438 }
439
440 }
441 ?>