[!!!][TASK] Extract testing framework for TYPO3
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / Persistence / RepositoryTest.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Tests\Unit\Persistence;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16 use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException;
17 use TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedMethodException;
18
19 /**
20 * Test case
21 */
22 class RepositoryTest extends \TYPO3\CMS\Components\TestingFramework\Core\UnitTestCase
23 {
24 /**
25 * @var \TYPO3\CMS\Extbase\Persistence\Repository|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Components\TestingFramework\Core\AccessibleObjectInterface
26 */
27 protected $repository;
28
29 /**
30 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
31 */
32 protected $mockObjectManager;
33
34 /**
35 * @var \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory
36 */
37 protected $mockQueryFactory;
38
39 /**
40 * @var \TYPO3\CMS\Extbase\Persistence\Generic\BackendInterface
41 */
42 protected $mockBackend;
43
44 /**
45 * @var \TYPO3\CMS\Extbase\Persistence\Generic\Session
46 */
47 protected $mockSession;
48
49 /**
50 * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface
51 */
52 protected $mockPersistenceManager;
53
54 /**
55 * @var \TYPO3\CMS\Extbase\Persistence\QueryInterface
56 */
57 protected $mockQuery;
58
59 /**
60 * @var \TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface
61 */
62 protected $mockQuerySettings;
63
64 /**
65 * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManager
66 */
67 protected $mockConfigurationManager;
68
69 protected function setUp()
70 {
71 $this->mockQueryFactory = $this->createMock(\TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory::class);
72 $this->mockQuery = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryInterface::class);
73 $this->mockQuerySettings = $this->createMock(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface::class);
74 $this->mockQuery->expects($this->any())->method('getQuerySettings')->will($this->returnValue($this->mockQuerySettings));
75 $this->mockQueryFactory->expects($this->any())->method('create')->will($this->returnValue($this->mockQuery));
76 $this->mockSession = $this->createMock(\TYPO3\CMS\Extbase\Persistence\Generic\Session::class);
77 $this->mockConfigurationManager = $this->createMock(\TYPO3\CMS\Extbase\Configuration\ConfigurationManager::class);
78 $this->mockBackend = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Backend::class, ['dummy'], [$this->mockConfigurationManager]);
79 $this->inject($this->mockBackend, 'session', $this->mockSession);
80 $this->mockPersistenceManager = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class, ['createQueryForType']);
81 $this->inject($this->mockBackend, 'persistenceManager', $this->mockPersistenceManager);
82 $this->inject($this->mockPersistenceManager, 'persistenceSession', $this->mockSession);
83 $this->inject($this->mockPersistenceManager, 'backend', $this->mockBackend);
84 $this->mockPersistenceManager->expects($this->any())->method('createQueryForType')->will($this->returnValue($this->mockQuery));
85 $this->mockObjectManager = $this->createMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
86 $this->repository = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Repository::class, ['dummy'], [$this->mockObjectManager]);
87 $this->repository->_set('persistenceManager', $this->mockPersistenceManager);
88 }
89
90 /**
91 * @test
92 */
93 public function abstractRepositoryImplementsRepositoryInterface()
94 {
95 $this->assertTrue($this->repository instanceof \TYPO3\CMS\Extbase\Persistence\RepositoryInterface);
96 }
97
98 /**
99 * @test
100 */
101 public function createQueryCallsPersistenceManagerWithExpectedClassName()
102 {
103 $mockPersistenceManager = $this->createMock(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class);
104 $mockPersistenceManager->expects($this->once())->method('createQueryForType')->with('ExpectedType');
105
106 $this->repository->_set('objectType', 'ExpectedType');
107 $this->inject($this->repository, 'persistenceManager', $mockPersistenceManager);
108
109 $this->repository->createQuery();
110 }
111
112 /**
113 * @test
114 */
115 public function createQuerySetsDefaultOrderingIfDefined()
116 {
117 $orderings = ['foo' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING];
118 $mockQuery = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryInterface::class);
119 $mockQuery->expects($this->once())->method('setOrderings')->with($orderings);
120 $mockPersistenceManager = $this->createMock(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class);
121 $mockPersistenceManager->expects($this->exactly(2))->method('createQueryForType')->with('ExpectedType')->will($this->returnValue($mockQuery));
122
123 $this->repository->_set('objectType', 'ExpectedType');
124 $this->inject($this->repository, 'persistenceManager', $mockPersistenceManager);
125 $this->repository->setDefaultOrderings($orderings);
126 $this->repository->createQuery();
127
128 $this->repository->setDefaultOrderings([]);
129 $this->repository->createQuery();
130 }
131
132 /**
133 * @test
134 */
135 public function findAllCreatesQueryAndReturnsResultOfExecuteCall()
136 {
137 $expectedResult = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryResultInterface::class);
138
139 $mockQuery = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryInterface::class);
140 $mockQuery->expects($this->once())->method('execute')->with()->will($this->returnValue($expectedResult));
141
142 $repository = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Repository::class)
143 ->setMethods(['createQuery'])
144 ->setConstructorArgs([$this->mockObjectManager])
145 ->getMock();
146 $repository->expects($this->once())->method('createQuery')->will($this->returnValue($mockQuery));
147
148 $this->assertSame($expectedResult, $repository->findAll());
149 }
150
151 /**
152 * @test
153 */
154 public function findByidentifierReturnsResultOfGetObjectByIdentifierCallFromBackend()
155 {
156 $identifier = '42';
157 $object = new \stdClass();
158
159 $expectedResult = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryResultInterface::class);
160 $expectedResult->expects($this->once())->method('getFirst')->will($this->returnValue($object));
161
162 $this->mockQuery->expects($this->any())->method('getQuerySettings')->will($this->returnValue($this->mockQuerySettings));
163 $this->mockQuery->expects($this->once())->method('matching')->will($this->returnValue($this->mockQuery));
164 $this->mockQuery->expects($this->once())->method('execute')->will($this->returnValue($expectedResult));
165
166 // skip backend, as we want to test the backend
167 $this->mockSession->expects($this->any())->method('hasIdentifier')->will($this->returnValue(false));
168 $this->assertSame($object, $this->repository->findByIdentifier($identifier));
169 }
170
171 /**
172 * @test
173 */
174 public function addDelegatesToPersistenceManager()
175 {
176 $object = new \stdClass();
177 $mockPersistenceManager = $this->createMock(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface::class);
178 $mockPersistenceManager->expects($this->once())->method('add')->with($object);
179 $this->inject($this->repository, 'persistenceManager', $mockPersistenceManager);
180 $this->repository->_set('objectType', get_class($object));
181 $this->repository->add($object);
182 }
183
184 /**
185 * @test
186 */
187 public function removeDelegatesToPersistenceManager()
188 {
189 $object = new \stdClass();
190 $mockPersistenceManager = $this->createMock(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface::class);
191 $mockPersistenceManager->expects($this->once())->method('remove')->with($object);
192 $this->inject($this->repository, 'persistenceManager', $mockPersistenceManager);
193 $this->repository->_set('objectType', get_class($object));
194 $this->repository->remove($object);
195 }
196
197 /**
198 * @test
199 */
200 public function updateDelegatesToPersistenceManager()
201 {
202 $object = new \stdClass();
203 $mockPersistenceManager = $this->createMock(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface::class);
204 $mockPersistenceManager->expects($this->once())->method('update')->with($object);
205 $this->inject($this->repository, 'persistenceManager', $mockPersistenceManager);
206 $this->repository->_set('objectType', get_class($object));
207 $this->repository->update($object);
208 }
209
210 /**
211 * @test
212 */
213 public function magicCallMethodAcceptsFindBySomethingCallsAndExecutesAQueryWithThatCriteria()
214 {
215 $mockQueryResult = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryResultInterface::class);
216 $mockQuery = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryInterface::class);
217 $mockQuery->expects($this->once())->method('equals')->with('foo', 'bar')->will($this->returnValue('matchCriteria'));
218 $mockQuery->expects($this->once())->method('matching')->with('matchCriteria')->will($this->returnValue($mockQuery));
219 $mockQuery->expects($this->once())->method('execute')->with()->will($this->returnValue($mockQueryResult));
220
221 $repository = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Repository::class)
222 ->setMethods(['createQuery'])
223 ->setConstructorArgs([$this->mockObjectManager])
224 ->getMock();
225 $repository->expects($this->once())->method('createQuery')->will($this->returnValue($mockQuery));
226
227 $this->assertSame($mockQueryResult, $repository->findByFoo('bar'));
228 }
229
230 /**
231 * @test
232 */
233 public function magicCallMethodAcceptsFindOneBySomethingCallsAndExecutesAQueryWithThatCriteria()
234 {
235 $object = new \stdClass();
236 $mockQueryResult = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryResultInterface::class);
237 $mockQueryResult->expects($this->once())->method('getFirst')->will($this->returnValue($object));
238 $mockQuery = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryInterface::class);
239 $mockQuery->expects($this->once())->method('equals')->with('foo', 'bar')->will($this->returnValue('matchCriteria'));
240 $mockQuery->expects($this->once())->method('matching')->with('matchCriteria')->will($this->returnValue($mockQuery));
241 $mockQuery->expects($this->once())->method('setLimit')->will($this->returnValue($mockQuery));
242 $mockQuery->expects($this->once())->method('execute')->will($this->returnValue($mockQueryResult));
243
244 $repository = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Repository::class)
245 ->setMethods(['createQuery'])
246 ->setConstructorArgs([$this->mockObjectManager])
247 ->getMock();
248 $repository->expects($this->once())->method('createQuery')->will($this->returnValue($mockQuery));
249
250 $this->assertSame($object, $repository->findOneByFoo('bar'));
251 }
252
253 /**
254 * @test
255 */
256 public function magicCallMethodAcceptsCountBySomethingCallsAndExecutesAQueryWithThatCriteria()
257 {
258 $mockQuery = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryInterface::class);
259 $mockQueryResult = $this->createMock(\TYPO3\CMS\Extbase\Persistence\QueryResultInterface::class);
260 $mockQuery->expects($this->once())->method('equals')->with('foo', 'bar')->will($this->returnValue('matchCriteria'));
261 $mockQuery->expects($this->once())->method('matching')->with('matchCriteria')->will($this->returnValue($mockQuery));
262 $mockQuery->expects($this->once())->method('execute')->will($this->returnValue($mockQueryResult));
263 $mockQueryResult->expects($this->once())->method('count')->will($this->returnValue(2));
264
265 $repository = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Repository::class)
266 ->setMethods(['createQuery'])
267 ->setConstructorArgs([$this->mockObjectManager])
268 ->getMock();
269 $repository->expects($this->once())->method('createQuery')->will($this->returnValue($mockQuery));
270
271 $this->assertSame(2, $repository->countByFoo('bar'));
272 }
273
274 /**
275 * @test
276 */
277 public function magicCallMethodTriggersAnErrorIfUnknownMethodsAreCalled()
278 {
279 $this->expectException(UnsupportedMethodException::class);
280 $this->expectExceptionCode(1233180480);
281 $repository = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Repository::class)
282 ->setMethods(['createQuery'])
283 ->setConstructorArgs([$this->mockObjectManager])
284 ->getMock();
285 $repository->__call('foo', []);
286 }
287
288 /**
289 * @test
290 */
291 public function addChecksObjectType()
292 {
293 $this->expectException(IllegalObjectTypeException::class);
294 $this->expectExceptionCode(1248363335);
295 $this->repository->_set('objectType', 'ExpectedObjectType');
296 $this->repository->add(new \stdClass());
297 }
298
299 /**
300 * @test
301 */
302 public function removeChecksObjectType()
303 {
304 $this->expectException(IllegalObjectTypeException::class);
305 $this->expectExceptionCode(1248363336);
306 $this->repository->_set('objectType', 'ExpectedObjectType');
307 $this->repository->remove(new \stdClass());
308 }
309
310 /**
311 * @test
312 */
313 public function updateChecksObjectType()
314 {
315 $this->expectException(IllegalObjectTypeException::class);
316 $this->expectExceptionCode(1249479625);
317 $repository = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Repository::class, ['dummy'], [$this->mockObjectManager]);
318 $repository->_set('objectType', 'ExpectedObjectType');
319
320 $repository->update(new \stdClass());
321 }
322
323 /**
324 * dataProvider for createQueryCallsQueryFactoryWithExpectedType
325 *
326 * @return array
327 */
328 public function modelAndRepositoryClassNames()
329 {
330 return [
331 ['Tx_BlogExample_Domain_Repository_BlogRepository', 'Tx_BlogExample_Domain_Model_Blog'],
332 ['_Domain_Repository_Content_PageRepository', '_Domain_Model_Content_Page'],
333 ['Tx_RepositoryExample_Domain_Repository_SomeModelRepository', 'Tx_RepositoryExample_Domain_Model_SomeModel'],
334 ['Tx_RepositoryExample_Domain_Repository_RepositoryRepository', 'Tx_RepositoryExample_Domain_Model_Repository'],
335 ['Tx_Repository_Domain_Repository_RepositoryRepository', 'Tx_Repository_Domain_Model_Repository']
336 ];
337 }
338
339 /**
340 * @test
341 * @dataProvider modelAndRepositoryClassNames
342 * @param string $repositoryClassName
343 * @param string $modelClassName
344 */
345 public function constructSetsObjectTypeFromClassName($repositoryClassName, $modelClassName)
346 {
347 $repositoryClassNameWithNS = __NAMESPACE__ . '\\' . $repositoryClassName;
348 eval('namespace ' . __NAMESPACE__ . '; class ' . $repositoryClassName . ' extends \\TYPO3\\CMS\\Extbase\\Persistence\\Repository {
349 protected function getRepositoryClassName() {
350 return \'' . $repositoryClassName . '\';
351 }
352 public function _getObjectType() {
353 return $this->objectType;
354 }
355 }');
356 $this->repository = new $repositoryClassNameWithNS($this->mockObjectManager);
357 $this->assertEquals($modelClassName, $this->repository->_getObjectType());
358 }
359
360 /**
361 * @test
362 */
363 public function createQueryReturnsQueryWithUnmodifiedDefaultQuerySettings()
364 {
365 $this->mockQuery = new \TYPO3\CMS\Extbase\Persistence\Generic\Query('foo');
366 $mockDefaultQuerySettings = $this->createMock(\TYPO3\CMS\Extbase\Persistence\Generic\QuerySettingsInterface::class);
367 $this->repository->setDefaultQuerySettings($mockDefaultQuerySettings);
368 $query = $this->repository->createQuery();
369 $instanceQuerySettings = $query->getQuerySettings();
370 $this->assertEquals($mockDefaultQuerySettings, $instanceQuerySettings);
371 $this->assertNotSame($mockDefaultQuerySettings, $instanceQuerySettings);
372 }
373
374 /**
375 * @test
376 */
377 public function findByUidReturnsResultOfGetObjectByIdentifierCall()
378 {
379 $fakeUid = '123';
380 $object = new \stdClass();
381 $repository = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Repository::class)
382 ->setMethods(['findByIdentifier'])
383 ->setConstructorArgs([$this->mockObjectManager])
384 ->getMock();
385 $expectedResult = $object;
386 $repository->expects($this->once())->method('findByIdentifier')->will($this->returnValue($object));
387 $actualResult = $repository->findByUid($fakeUid);
388 $this->assertSame($expectedResult, $actualResult);
389 }
390
391 /**
392 * @test
393 */
394 public function updateRejectsObjectsOfWrongType()
395 {
396 $this->expectException(IllegalObjectTypeException::class);
397 $this->expectExceptionCode(1249479625);
398 $this->repository->_set('objectType', 'Foo');
399 $this->repository->update(new \stdClass());
400 }
401
402 /**
403 * @test
404 */
405 public function magicCallMethodReturnsFirstArrayKeyInFindOneBySomethingIfQueryReturnsRawResult()
406 {
407 $queryResultArray = [
408 0 => [
409 'foo' => 'bar',
410 ],
411 ];
412 $this->mockQuery->expects($this->once())->method('equals')->with('foo', 'bar')->will($this->returnValue('matchCriteria'));
413 $this->mockQuery->expects($this->once())->method('matching')->with('matchCriteria')->will($this->returnValue($this->mockQuery));
414 $this->mockQuery->expects($this->once())->method('setLimit')->with(1)->will($this->returnValue($this->mockQuery));
415 $this->mockQuery->expects($this->once())->method('execute')->will($this->returnValue($queryResultArray));
416 $this->assertSame(['foo' => 'bar'], $this->repository->findOneByFoo('bar'));
417 }
418
419 /**
420 * @test
421 */
422 public function magicCallMethodReturnsNullInFindOneBySomethingIfQueryReturnsEmptyRawResult()
423 {
424 $queryResultArray = [];
425 $this->mockQuery->expects($this->once())->method('equals')->with('foo', 'bar')->will($this->returnValue('matchCriteria'));
426 $this->mockQuery->expects($this->once())->method('matching')->with('matchCriteria')->will($this->returnValue($this->mockQuery));
427 $this->mockQuery->expects($this->once())->method('setLimit')->with(1)->will($this->returnValue($this->mockQuery));
428 $this->mockQuery->expects($this->once())->method('execute')->will($this->returnValue($queryResultArray));
429 $this->assertNull($this->repository->findOneByFoo('bar'));
430 }
431 }