4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Serializer\Tests\Normalizer;
14 use Doctrine\Common\Annotations\AnnotationReader;
15 use PHPUnit\Framework\TestCase;
16 use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
17 use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
18 use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
19 use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
20 use Symfony\Component\Serializer\Serializer;
21 use Symfony\Component\Serializer\SerializerInterface;
22 use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy;
23 use Symfony\Component\Serializer\Tests\Fixtures\GroupDummyChild;
24 use Symfony\Component\Serializer\Tests\Fixtures\MaxDepthDummy;
25 use Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy;
26 use Symfony\Component\Serializer\Tests\Fixtures\PropertySiblingHolder;
28 class PropertyNormalizerTest extends TestCase
31 * @var PropertyNormalizer
35 * @var SerializerInterface
39 protected function setUp()
41 $this->serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
42 $this->normalizer = new PropertyNormalizer();
43 $this->normalizer->setSerializer($this->serializer);
46 public function testNormalize()
48 $obj = new PropertyDummy();
51 $obj->setCamelCase('camelcase');
53 array('foo' => 'foo', 'bar' => 'bar', 'camelCase' => 'camelcase'),
54 $this->normalizer->normalize($obj, 'any')
58 public function testDenormalize()
60 $obj = $this->normalizer->denormalize(
61 array('foo' => 'foo', 'bar' => 'bar'),
62 __NAMESPACE__.'\PropertyDummy',
65 $this->assertEquals('foo', $obj->foo);
66 $this->assertEquals('bar', $obj->getBar());
69 public function testNormalizeWithParentClass()
71 $group = new GroupDummyChild();
72 $group->setBaz('baz');
73 $group->setFoo('foo');
74 $group->setBar('bar');
75 $group->setKevin('Kevin');
76 $group->setCoopTilleuls('coop');
78 array('foo' => 'foo', 'bar' => 'bar', 'kevin' => 'Kevin',
79 'coopTilleuls' => 'coop', 'fooBar' => null, 'symfony' => null, 'baz' => 'baz', ),
80 $this->normalizer->normalize($group, 'any')
84 public function testDenormalizeWithParentClass()
86 $obj = $this->normalizer->denormalize(
87 array('foo' => 'foo', 'bar' => 'bar', 'kevin' => 'Kevin', 'baz' => 'baz'),
88 GroupDummyChild::class,
91 $this->assertEquals('foo', $obj->getFoo());
92 $this->assertEquals('bar', $obj->getBar());
93 $this->assertEquals('Kevin', $obj->getKevin());
94 $this->assertEquals('baz', $obj->getBaz());
95 $this->assertNull($obj->getSymfony());
98 public function testConstructorDenormalize()
100 $obj = $this->normalizer->denormalize(
101 array('foo' => 'foo', 'bar' => 'bar'),
102 __NAMESPACE__.'\PropertyConstructorDummy',
105 $this->assertEquals('foo', $obj->getFoo());
106 $this->assertEquals('bar', $obj->getBar());
109 public function testConstructorDenormalizeWithNullArgument()
111 $obj = $this->normalizer->denormalize(
112 array('foo' => null, 'bar' => 'bar'),
113 __NAMESPACE__.'\PropertyConstructorDummy', '
116 $this->assertNull($obj->getFoo());
117 $this->assertEquals('bar', $obj->getBar());
121 * @dataProvider provideCallbacks
123 public function testCallbacks($callbacks, $value, $result, $message)
125 $this->normalizer->setCallbacks($callbacks);
127 $obj = new PropertyConstructorDummy('', $value);
131 $this->normalizer->normalize($obj, 'any'),
137 * @expectedException \InvalidArgumentException
139 public function testUncallableCallbacks()
141 $this->normalizer->setCallbacks(array('bar' => null));
143 $obj = new PropertyConstructorDummy('baz', 'quux');
145 $this->normalizer->normalize($obj, 'any');
148 public function testIgnoredAttributes()
150 $this->normalizer->setIgnoredAttributes(array('foo', 'bar', 'camelCase'));
152 $obj = new PropertyDummy();
158 $this->normalizer->normalize($obj, 'any')
162 public function testGroupsNormalize()
164 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
165 $this->normalizer = new PropertyNormalizer($classMetadataFactory);
166 $this->normalizer->setSerializer($this->serializer);
168 $obj = new GroupDummy();
171 $obj->setFooBar('fooBar');
172 $obj->setSymfony('symfony');
173 $obj->setKevin('kevin');
174 $obj->setCoopTilleuls('coopTilleuls');
176 $this->assertEquals(array(
178 ), $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('c'))));
180 // The PropertyNormalizer is also able to hydrate properties from parent classes
181 $this->assertEquals(array(
182 'symfony' => 'symfony',
184 'fooBar' => 'fooBar',
187 'coopTilleuls' => 'coopTilleuls',
188 ), $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('a', 'c'))));
191 public function testGroupsDenormalize()
193 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
194 $this->normalizer = new PropertyNormalizer($classMetadataFactory);
195 $this->normalizer->setSerializer($this->serializer);
197 $obj = new GroupDummy();
200 $toNormalize = array('foo' => 'foo', 'bar' => 'bar');
202 $normalized = $this->normalizer->denormalize(
204 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
206 array(PropertyNormalizer::GROUPS => array('a'))
208 $this->assertEquals($obj, $normalized);
212 $normalized = $this->normalizer->denormalize(
214 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
216 array(PropertyNormalizer::GROUPS => array('a', 'b'))
218 $this->assertEquals($obj, $normalized);
221 public function testGroupsNormalizeWithNameConverter()
223 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
224 $this->normalizer = new PropertyNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
225 $this->normalizer->setSerializer($this->serializer);
227 $obj = new GroupDummy();
228 $obj->setFooBar('@dunglas');
229 $obj->setSymfony('@coopTilleuls');
230 $obj->setCoopTilleuls('les-tilleuls.coop');
235 'foo_bar' => '@dunglas',
236 'symfony' => '@coopTilleuls',
238 $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('name_converter')))
242 public function testGroupsDenormalizeWithNameConverter()
244 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
245 $this->normalizer = new PropertyNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
246 $this->normalizer->setSerializer($this->serializer);
248 $obj = new GroupDummy();
249 $obj->setFooBar('@dunglas');
250 $obj->setSymfony('@coopTilleuls');
254 $this->normalizer->denormalize(array(
256 'foo_bar' => '@dunglas',
257 'symfony' => '@coopTilleuls',
258 'coop_tilleuls' => 'les-tilleuls.coop',
259 ), 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy', null, array(PropertyNormalizer::GROUPS => array('name_converter')))
263 public function provideCallbacks()
268 'bar' => function ($bar) {
273 array('foo' => '', 'bar' => 'baz'),
278 'bar' => function ($bar) {
283 array('foo' => '', 'bar' => null),
288 'bar' => function ($bar) {
289 return $bar->format('d-m-Y H:i:s');
292 new \DateTime('2011-09-10 06:30:00'),
293 array('foo' => '', 'bar' => '10-09-2011 06:30:00'),
298 'bar' => function ($bars) {
300 foreach ($bars as $bar) {
301 $foos .= $bar->getFoo();
307 array(new PropertyConstructorDummy('baz', ''), new PropertyConstructorDummy('quux', '')),
308 array('foo' => '', 'bar' => 'bazquux'),
309 'Collect a property',
313 'bar' => function ($bars) {
317 array(new PropertyConstructorDummy('baz', ''), new PropertyConstructorDummy('quux', '')),
318 array('foo' => '', 'bar' => 2),
325 * @expectedException \Symfony\Component\Serializer\Exception\CircularReferenceException
327 public function testUnableToNormalizeCircularReference()
329 $serializer = new Serializer(array($this->normalizer));
330 $this->normalizer->setSerializer($serializer);
331 $this->normalizer->setCircularReferenceLimit(2);
333 $obj = new PropertyCircularReferenceDummy();
335 $this->normalizer->normalize($obj);
338 public function testSiblingReference()
340 $serializer = new Serializer(array($this->normalizer));
341 $this->normalizer->setSerializer($serializer);
343 $siblingHolder = new PropertySiblingHolder();
346 'sibling0' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
347 'sibling1' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
348 'sibling2' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
350 $this->assertEquals($expected, $this->normalizer->normalize($siblingHolder));
353 public function testCircularReferenceHandler()
355 $serializer = new Serializer(array($this->normalizer));
356 $this->normalizer->setSerializer($serializer);
357 $this->normalizer->setCircularReferenceHandler(function ($obj) {
358 return get_class($obj);
361 $obj = new PropertyCircularReferenceDummy();
363 $expected = array('me' => 'Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy');
364 $this->assertEquals($expected, $this->normalizer->normalize($obj));
367 public function testDenormalizeNonExistingAttribute()
371 $this->normalizer->denormalize(array('non_existing' => true), __NAMESPACE__.'\PropertyDummy')
375 public function testDenormalizeShouldIgnoreStaticProperty()
377 $obj = $this->normalizer->denormalize(array('outOfScope' => true), __NAMESPACE__.'\PropertyDummy');
379 $this->assertEquals(new PropertyDummy(), $obj);
380 $this->assertEquals('out_of_scope', PropertyDummy::$outOfScope);
384 * @expectedException \Symfony\Component\Serializer\Exception\LogicException
385 * @expectedExceptionMessage Cannot normalize attribute "bar" because the injected serializer is not a normalizer
387 public function testUnableToNormalizeObjectAttribute()
389 $serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
390 $this->normalizer->setSerializer($serializer);
392 $obj = new PropertyDummy();
393 $object = new \stdClass();
394 $obj->setBar($object);
396 $this->normalizer->normalize($obj, 'any');
399 public function testNoTraversableSupport()
401 $this->assertFalse($this->normalizer->supportsNormalization(new \ArrayObject()));
404 public function testNoStaticPropertySupport()
406 $this->assertFalse($this->normalizer->supportsNormalization(new StaticPropertyDummy()));
409 public function testMaxDepth()
411 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
412 $this->normalizer = new PropertyNormalizer($classMetadataFactory);
413 $serializer = new Serializer(array($this->normalizer));
414 $this->normalizer->setSerializer($serializer);
416 $level1 = new MaxDepthDummy();
417 $level1->foo = 'level1';
419 $level2 = new MaxDepthDummy();
420 $level2->foo = 'level2';
421 $level1->child = $level2;
423 $level3 = new MaxDepthDummy();
424 $level3->foo = 'level3';
425 $level2->child = $level3;
427 $result = $serializer->normalize($level1, null, array(PropertyNormalizer::ENABLE_MAX_DEPTH => true));
442 $this->assertEquals($expected, $result);
445 public function testInheritedPropertiesSupport()
447 $this->assertTrue($this->normalizer->supportsNormalization(new PropertyChildDummy()));
453 public static $outOfScope = 'out_of_scope';
456 protected $camelCase;
458 public function getBar()
463 public function setBar($bar)
468 public function getCamelCase()
470 return $this->camelCase;
473 public function setCamelCase($camelCase)
475 $this->camelCase = $camelCase;
479 class PropertyConstructorDummy
484 public function __construct($foo, $bar)
490 public function getFoo()
495 public function getBar()
501 class PropertyCamelizedDummy
503 private $kevinDunglas;
507 public function __construct($kevinDunglas = null)
509 $this->kevinDunglas = $kevinDunglas;
513 class StaticPropertyDummy
515 private static $property = 'value';
518 class PropertyParentDummy
520 private $foo = 'bar';
523 class PropertyChildDummy extends PropertyParentDummy