[TASK] Inherit from UnitTestCase in ext:extbase
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / Property / TypeConverter / PersistentObjectConverterTest.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Tests\Unit\Property\TypeConverter;
3
4 /* *
5 * This script belongs to the Extbase framework. *
6 * *
7 * It is free software; you can redistribute it and/or modify it under *
8 * the terms of the GNU Lesser General Public License as published by the *
9 * Free Software Foundation, either version 3 of the License, or (at your *
10 * option) any later version. *
11 * *
12 * This script is distributed in the hope that it will be useful, but *
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- *
14 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser *
15 * General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with the script. *
19 * If not, see http://www.gnu.org/licenses/lgpl.html *
20 * *
21 * The TYPO3 project - inspiring people to share! *
22 * */
23
24 /**
25 * Test case
26 */
27 class PersistentObjectConverterTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
28
29 /**
30 * @var \TYPO3\CMS\Extbase\Property\TypeConverterInterface
31 */
32 protected $converter;
33
34 protected $mockReflectionService;
35 protected $mockPersistenceManager;
36 protected $mockObjectManager;
37
38 public function setUp() {
39 $this->converter = new \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter();
40 $this->mockReflectionService = $this->getMock('TYPO3\CMS\Extbase\Reflection\ReflectionService');
41 $this->inject($this->converter, 'reflectionService', $this->mockReflectionService);
42
43 $this->mockPersistenceManager = $this->getMock('TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface');
44 $this->inject($this->converter, 'persistenceManager', $this->mockPersistenceManager);
45
46 $this->mockObjectManager = $this->getMock('TYPO3\CMS\Extbase\Object\ObjectManagerInterface');
47 $this->mockObjectManager->expects($this->any())
48 ->method('get')
49 ->will($this->returnCallback(function() {
50 $args = func_get_args();
51 $reflectionClass = new \ReflectionClass(array_shift($args));
52 if (empty($args)) {
53 return $reflectionClass->newInstance();
54 } else {
55 return $reflectionClass->newInstanceArgs($args);
56 }
57 }));
58 $this->inject($this->converter, 'objectManager', $this->mockObjectManager);
59 }
60
61 /**
62 * @test
63 */
64 public function checkMetadata() {
65 $this->assertEquals(array('string', 'array'), $this->converter->getSupportedSourceTypes(), 'Source types do not match');
66 $this->assertEquals('object', $this->converter->getSupportedTargetType(), 'Target type does not match');
67 $this->assertEquals(1, $this->converter->getPriority(), 'Priority does not match');
68 }
69
70 public function dataProviderForCanConvert() {
71 return array(
72 array(TRUE, FALSE, TRUE),
73 // is entity => can convert
74 array(FALSE, TRUE, TRUE),
75 // is valueobject => can convert
76 array(FALSE, FALSE, FALSE),
77 // is no entity and no value object => can not convert
78 );
79 }
80
81 /**
82 * @test
83 * @dataProvider dataProviderForCanConvert
84 */
85 public function canConvertFromReturnsTrueIfClassIsTaggedWithEntityOrValueObject($isEntity, $isValueObject, $expected) {
86 $className = uniqid('Test_Class');
87 if ($isEntity) {
88 eval("class {$className} extends Tx_Extbase_DomainObject_AbstractEntity {}");
89 } elseif ($isValueObject) {
90 eval("class {$className} extends Tx_Extbase_DomainObject_AbstractValueObject {}");
91 } else {
92 eval("class {$className} {}");
93 }
94 $this->assertEquals($expected, $this->converter->canConvertFrom('myInputData', $className));
95 }
96
97 /**
98 * @test
99 */
100 public function getSourceChildPropertiesToBeConvertedReturnsAllPropertiesExceptTheIdentityProperty() {
101 $source = array(
102 'k1' => 'v1',
103 '__identity' => 'someIdentity',
104 'k2' => 'v2'
105 );
106 $expected = array(
107 'k1' => 'v1',
108 'k2' => 'v2'
109 );
110 $this->assertEquals($expected, $this->converter->getSourceChildPropertiesToBeConverted($source));
111 }
112
113 /**
114 * @test
115 */
116 public function getTypeOfChildPropertyShouldUseReflectionServiceToDetermineType() {
117 $mockSchema = $this->getMockBuilder('TYPO3\\CMS\\Extbase\\Reflection\\ClassSchema')->disableOriginalConstructor()->getMock();
118 $this->mockReflectionService->expects($this->any())->method('getClassSchema')->with('TheTargetType')->will($this->returnValue($mockSchema));
119
120 $mockSchema->expects($this->any())->method('hasProperty')->with('thePropertyName')->will($this->returnValue(TRUE));
121 $mockSchema->expects($this->any())->method('getProperty')->with('thePropertyName')->will($this->returnValue(array(
122 'type' => 'TheTypeOfSubObject',
123 'elementType' => NULL
124 )));
125 $configuration = $this->buildConfiguration(array());
126 $this->assertEquals('TheTypeOfSubObject', $this->converter->getTypeOfChildProperty('TheTargetType', 'thePropertyName', $configuration));
127 }
128
129 /**
130 * @test
131 */
132 public function getTypeOfChildPropertyShouldUseConfiguredTypeIfItWasSet() {
133 $this->mockReflectionService->expects($this->never())->method('getClassSchema');
134
135 $configuration = $this->buildConfiguration(array());
136 $configuration->forProperty('thePropertyName')->setTypeConverterOption('TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter', \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_TARGET_TYPE, 'Foo\Bar');
137 $this->assertEquals('Foo\Bar', $this->converter->getTypeOfChildProperty('foo', 'thePropertyName', $configuration));
138 }
139
140 /**
141 * @test
142 */
143 public function convertFromShouldFetchObjectFromPersistenceIfUuidStringIsGiven() {
144 $identifier = '17';
145 $object = new \stdClass();
146
147 $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with($identifier)->will($this->returnValue($object));
148 $this->assertSame($object, $this->converter->convertFrom($identifier, 'MySpecialType'));
149 }
150
151 /**
152 * @test
153 */
154 public function convertFromShouldFetchObjectFromPersistenceIfuidStringIsGiven() {
155 $identifier = '17';
156 $object = new \stdClass();
157
158 $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with($identifier)->will($this->returnValue($object));
159 $this->assertSame($object, $this->converter->convertFrom($identifier, 'MySpecialType'));
160 }
161
162 /**
163 * @test
164 */
165 public function convertFromShouldFetchObjectFromPersistenceIfOnlyIdentityArrayGiven() {
166 $identifier = '12345';
167 $object = new \stdClass();
168
169 $source = array(
170 '__identity' => $identifier
171 );
172 $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with($identifier)->will($this->returnValue($object));
173 $this->assertSame($object, $this->converter->convertFrom($source, 'MySpecialType'));
174 }
175
176 /**
177 * @test
178 * @expectedException \TYPO3\CMS\Extbase\Property\Exception\InvalidPropertyMappingConfigurationException
179 */
180 public function convertFromShouldThrowExceptionIfObjectNeedsToBeModifiedButConfigurationIsNotSet() {
181 $identifier = '12345';
182 $object = new \stdClass();
183 $object->someProperty = 'asdf';
184
185 $source = array(
186 '__identity' => $identifier,
187 'foo' => 'bar'
188 );
189 $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with($identifier)->will($this->returnValue($object));
190 $this->converter->convertFrom($source, 'MySpecialType');
191 }
192
193 /**
194 * @param array $typeConverterOptions
195 * @return \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration
196 */
197 protected function buildConfiguration($typeConverterOptions) {
198 $configuration = new \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration();
199 $configuration->setTypeConverterOptions('TYPO3\\CMS\\Extbase\\Property\\TypeConverter\\PersistentObjectConverter', $typeConverterOptions);
200 return $configuration;
201 }
202
203 /**
204 * @param integer $numberOfResults
205 * @param Matcher $howOftenIsGetFirstCalled
206 * @return \stdClass
207 */
208 public function setupMockQuery($numberOfResults, $howOftenIsGetFirstCalled) {
209 $mockClassSchema = $this->getMock('TYPO3\\CMS\\Extbase\\Reflection\\ClassSchema', array(), array('Dummy'));
210 $mockClassSchema->expects($this->any())->method('getIdentityProperties')->will($this->returnValue(array('key1' => 'someType')));
211 $this->mockReflectionService->expects($this->any())->method('getClassSchema')->with('SomeType')->will($this->returnValue($mockClassSchema));
212
213 $mockConstraint = $this->getMockBuilder('TYPO3\CMS\Extbase\Persistence\Generic\Qom\Comparison')->disableOriginalConstructor()->getMock();
214
215 $mockObject = new \stdClass();
216 $mockQuery = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\QueryInterface');
217 $mockQueryResult = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\QueryResultInterface');
218 $mockQueryResult->expects($this->any())->method('count')->will($this->returnValue($numberOfResults));
219 $mockQueryResult->expects($howOftenIsGetFirstCalled)->method('getFirst')->will($this->returnValue($mockObject));
220 $mockQuery->expects($this->any())->method('equals')->with('key1', 'value1')->will($this->returnValue($mockConstraint));
221 $mockQuery->expects($this->any())->method('matching')->with($mockConstraint)->will($this->returnValue($mockQuery));
222 $mockQuery->expects($this->any())->method('execute')->will($this->returnValue($mockQueryResult));
223
224 $this->mockPersistenceManager->expects($this->any())->method('createQueryForType')->with('SomeType')->will($this->returnValue($mockQuery));
225
226 return $mockObject;
227 }
228
229 /**
230 * @test
231 * @expectedException \TYPO3\CMS\Extbase\Property\Exception\TargetNotFoundException
232 */
233 public function convertFromShouldReturnExceptionIfNoMatchingObjectWasFound() {
234 $this->setupMockQuery(0, $this->never());
235 $this->mockReflectionService->expects($this->never())->method('getClassSchema');
236
237 $source = array(
238 '__identity' => 123
239 );
240 $actual = $this->converter->convertFrom($source, 'SomeType');
241 $this->assertNull($actual);
242 }
243
244 /**
245 * @test
246 * @expectedException \TYPO3\CMS\Extbase\Property\Exception\DuplicateObjectException
247 */
248 public function convertFromShouldThrowExceptionIfMoreThanOneObjectWasFound() {
249 $this->setupMockQuery(2, $this->never());
250
251 $source = array(
252 '__identity' => 666
253 );
254 $this->mockPersistenceManager->expects($this->any())->method('getObjectByIdentifier')->with(666)->will($this->throwException(new \TYPO3\CMS\Extbase\Property\Exception\DuplicateObjectException));
255 $this->converter->convertFrom($source, 'SomeType');
256 }
257
258 /**
259 * @test
260 * @expectedException \TYPO3\CMS\Extbase\Property\Exception\InvalidPropertyMappingConfigurationException
261 */
262 public function convertFromShouldThrowExceptionIfObjectNeedsToBeCreatedButConfigurationIsNotSet() {
263 $source = array(
264 'foo' => 'bar'
265 );
266 $this->converter->convertFrom($source, 'MySpecialType');
267 }
268
269 /**
270 * @test
271 */
272 public function convertFromShouldCreateObject() {
273 $source = array(
274 'propertyX' => 'bar'
275 );
276 $convertedChildProperties = array(
277 'property1' => 'bar'
278 );
279 $expectedObject = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters();
280 $expectedObject->property1 = 'bar';
281
282 $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters', '__construct')->will($this->throwException(new \ReflectionException()));
283 $this->mockObjectManager->expects($this->any())->method('getClassNameByObjectName')->with('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters')->will($this->returnValue('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters'));
284 $configuration = $this->buildConfiguration(array(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => TRUE));
285 $result = $this->converter->convertFrom($source, 'TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters', $convertedChildProperties, $configuration);
286 $this->assertEquals($expectedObject, $result);
287 }
288
289 /**
290 * @test
291 * @expectedException \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException
292 */
293 public function convertFromShouldThrowExceptionIfPropertyOnTargetObjectCouldNotBeSet() {
294 $source = array(
295 'propertyX' => 'bar'
296 );
297 $object = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSetters();
298 $convertedChildProperties = array(
299 'propertyNotExisting' => 'bar'
300 );
301 $this->mockObjectManager->expects($this->any())->method('get')->with('TYPO3\\CMS\\Extbase\\Tests\\Fixture\\ClassWithSetters')->will($this->returnValue($object));
302 $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with('TYPO3\\CMS\\Extbase\\Tests\\Fixture\\ClassWithSetters', '__construct')->will($this->returnValue(array()));
303 $configuration = $this->buildConfiguration(array(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => TRUE));
304 $result = $this->converter->convertFrom($source, 'TYPO3\\CMS\\Extbase\\Tests\\Fixture\\ClassWithSetters', $convertedChildProperties, $configuration);
305 $this->assertSame($object, $result);
306 }
307
308 /**
309 * @test
310 */
311 public function convertFromShouldCreateObjectWhenThereAreConstructorParameters() {
312 $source = array(
313 'propertyX' => 'bar'
314 );
315 $convertedChildProperties = array(
316 'property1' => 'param1',
317 'property2' => 'bar'
318 );
319 $expectedObject = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor('param1');
320 $expectedObject->setProperty2('bar');
321
322 $this->mockReflectionService
323 ->expects($this->any())
324 ->method('getMethodParameters')
325 ->with('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor', '__construct')
326 ->will($this->returnValue(array(
327 'property1' => array('optional' => FALSE)
328 )));
329 $this->mockReflectionService
330 ->expects($this->any())
331 ->method('hasMethod')
332 ->with('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor', '__construct')
333 ->will($this->returnValue(TRUE));
334 $this->mockObjectManager->expects($this->any())->method('getClassNameByObjectName')->with('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor')->will($this->returnValue('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor'));
335 $configuration = $this->buildConfiguration(array(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => TRUE));
336 $result = $this->converter->convertFrom($source, 'TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor', $convertedChildProperties, $configuration);
337 $this->assertEquals($expectedObject, $result);
338 $this->assertEquals('bar', $expectedObject->getProperty2());
339 }
340
341 /**
342 * @test
343 */
344 public function convertFromShouldCreateObjectWhenThereAreOptionalConstructorParameters() {
345 $source = array(
346 'propertyX' => 'bar'
347 );
348 $expectedObject = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor('thisIsTheDefaultValue');
349
350 $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor', '__construct')->will($this->returnValue(array(
351 'property1' => array('optional' => TRUE, 'defaultValue' => 'thisIsTheDefaultValue')
352 )));
353 $this->mockReflectionService
354 ->expects($this->any())
355 ->method('hasMethod')
356 ->with('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor', '__construct')
357 ->will($this->returnValue(TRUE));
358 $this->mockObjectManager->expects($this->any())->method('getClassNameByObjectName')->with('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor')->will($this->returnValue('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor'));
359 $configuration = $this->buildConfiguration(array(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => TRUE));
360 $result = $this->converter->convertFrom($source, 'TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor', array(), $configuration);
361 $this->assertEquals($expectedObject, $result);
362 }
363
364 /**
365 * @test
366 * @expectedException \TYPO3\CMS\Extbase\Property\Exception\InvalidTargetException
367 */
368 public function convertFromShouldThrowExceptionIfRequiredConstructorParameterWasNotFound() {
369 $source = array(
370 'propertyX' => 'bar'
371 );
372 $object = new \TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor('param1');
373 $convertedChildProperties = array(
374 'property2' => 'bar'
375 );
376
377 $this->mockReflectionService->expects($this->any())->method('getMethodParameters')->with('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor', '__construct')->will($this->returnValue(array(
378 'property1' => array('optional' => FALSE)
379 )));
380 $this->mockReflectionService
381 ->expects($this->any())
382 ->method('hasMethod')
383 ->with('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor', '__construct')
384 ->will($this->returnValue(TRUE));
385 $this->mockObjectManager->expects($this->any())->method('getClassNameByObjectName')->with('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor')->will($this->returnValue('TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor'));
386 $configuration = $this->buildConfiguration(array(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED => TRUE));
387 $result = $this->converter->convertFrom($source, 'TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor', $convertedChildProperties, $configuration);
388 $this->assertSame($object, $result);
389 }
390
391 /**
392 * @test
393 */
394 public function convertFromShouldReturnNullForEmptyString() {
395 $source = '';
396 $result = $this->converter->convertFrom($source, 'TYPO3\CMS\Extbase\Tests\Fixture\ClassWithSettersAndConstructor');
397 $this->assertNull($result);
398 }
399
400 }