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\PropertyCircularReferenceDummy;
24 use Symfony\Component\Serializer\Tests\Fixtures\PropertySiblingHolder;
26 class PropertyNormalizerTest extends TestCase
29 * @var PropertyNormalizer
33 * @var SerializerInterface
37 protected function setUp()
39 $this->serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
40 $this->normalizer = new PropertyNormalizer();
41 $this->normalizer->setSerializer($this->serializer);
44 public function testNormalize()
46 $obj = new PropertyDummy();
49 $obj->setCamelCase('camelcase');
51 array('foo' => 'foo', 'bar' => 'bar', 'camelCase' => 'camelcase'),
52 $this->normalizer->normalize($obj, 'any')
56 public function testDenormalize()
58 $obj = $this->normalizer->denormalize(
59 array('foo' => 'foo', 'bar' => 'bar'),
60 __NAMESPACE__.'\PropertyDummy',
63 $this->assertEquals('foo', $obj->foo);
64 $this->assertEquals('bar', $obj->getBar());
70 public function testLegacyDenormalizeOnCamelCaseFormat()
72 $this->normalizer->setCamelizedAttributes(array('camel_case'));
73 $obj = $this->normalizer->denormalize(
74 array('camel_case' => 'value'),
75 __NAMESPACE__.'\PropertyDummy'
77 $this->assertEquals('value', $obj->getCamelCase());
83 public function testLegacyCamelizedAttributesNormalize()
85 $obj = new PropertyCamelizedDummy('dunglas.fr');
86 $obj->fooBar = 'les-tilleuls.coop';
87 $obj->bar_foo = 'lostinthesupermarket.fr';
89 $this->normalizer->setCamelizedAttributes(array('kevin_dunglas'));
90 $this->assertEquals($this->normalizer->normalize($obj), array(
91 'kevin_dunglas' => 'dunglas.fr',
92 'fooBar' => 'les-tilleuls.coop',
93 'bar_foo' => 'lostinthesupermarket.fr',
96 $this->normalizer->setCamelizedAttributes(array('foo_bar'));
97 $this->assertEquals($this->normalizer->normalize($obj), array(
98 'kevinDunglas' => 'dunglas.fr',
99 'foo_bar' => 'les-tilleuls.coop',
100 'bar_foo' => 'lostinthesupermarket.fr',
107 public function testLegacyCamelizedAttributesDenormalize()
109 $obj = new PropertyCamelizedDummy('dunglas.fr');
110 $obj->fooBar = 'les-tilleuls.coop';
111 $obj->bar_foo = 'lostinthesupermarket.fr';
113 $this->normalizer->setCamelizedAttributes(array('kevin_dunglas'));
114 $this->assertEquals($this->normalizer->denormalize(array(
115 'kevin_dunglas' => 'dunglas.fr',
116 'fooBar' => 'les-tilleuls.coop',
117 'bar_foo' => 'lostinthesupermarket.fr',
118 ), __NAMESPACE__.'\PropertyCamelizedDummy'), $obj);
120 $this->normalizer->setCamelizedAttributes(array('foo_bar'));
121 $this->assertEquals($this->normalizer->denormalize(array(
122 'kevinDunglas' => 'dunglas.fr',
123 'foo_bar' => 'les-tilleuls.coop',
124 'bar_foo' => 'lostinthesupermarket.fr',
125 ), __NAMESPACE__.'\PropertyCamelizedDummy'), $obj);
128 public function testNameConverterSupport()
130 $this->normalizer = new PropertyNormalizer(null, new CamelCaseToSnakeCaseNameConverter());
131 $obj = $this->normalizer->denormalize(
132 array('camel_case' => 'camelCase'),
133 __NAMESPACE__.'\PropertyDummy'
135 $this->assertEquals('camelCase', $obj->getCamelCase());
138 public function testConstructorDenormalize()
140 $obj = $this->normalizer->denormalize(
141 array('foo' => 'foo', 'bar' => 'bar'),
142 __NAMESPACE__.'\PropertyConstructorDummy',
145 $this->assertEquals('foo', $obj->getFoo());
146 $this->assertEquals('bar', $obj->getBar());
149 public function testConstructorDenormalizeWithNullArgument()
151 $obj = $this->normalizer->denormalize(
152 array('foo' => null, 'bar' => 'bar'),
153 __NAMESPACE__.'\PropertyConstructorDummy', '
156 $this->assertNull($obj->getFoo());
157 $this->assertEquals('bar', $obj->getBar());
161 * @dataProvider provideCallbacks
163 public function testCallbacks($callbacks, $value, $result, $message)
165 $this->normalizer->setCallbacks($callbacks);
167 $obj = new PropertyConstructorDummy('', $value);
171 $this->normalizer->normalize($obj, 'any'),
177 * @expectedException \InvalidArgumentException
179 public function testUncallableCallbacks()
181 $this->normalizer->setCallbacks(array('bar' => null));
183 $obj = new PropertyConstructorDummy('baz', 'quux');
185 $this->normalizer->normalize($obj, 'any');
188 public function testIgnoredAttributes()
190 $this->normalizer->setIgnoredAttributes(array('foo', 'bar', 'camelCase'));
192 $obj = new PropertyDummy();
198 $this->normalizer->normalize($obj, 'any')
202 public function testGroupsNormalize()
204 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
205 $this->normalizer = new PropertyNormalizer($classMetadataFactory);
206 $this->normalizer->setSerializer($this->serializer);
208 $obj = new GroupDummy();
211 $obj->setFooBar('fooBar');
212 $obj->setSymfony('symfony');
213 $obj->setKevin('kevin');
214 $obj->setCoopTilleuls('coopTilleuls');
216 $this->assertEquals(array(
218 ), $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('c'))));
220 // The PropertyNormalizer is not able to hydrate properties from parent classes
221 $this->assertEquals(array(
222 'symfony' => 'symfony',
224 'fooBar' => 'fooBar',
226 ), $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('a', 'c'))));
229 public function testGroupsDenormalize()
231 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
232 $this->normalizer = new PropertyNormalizer($classMetadataFactory);
233 $this->normalizer->setSerializer($this->serializer);
235 $obj = new GroupDummy();
238 $toNormalize = array('foo' => 'foo', 'bar' => 'bar');
240 $normalized = $this->normalizer->denormalize(
242 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
244 array(PropertyNormalizer::GROUPS => array('a'))
246 $this->assertEquals($obj, $normalized);
250 $normalized = $this->normalizer->denormalize(
252 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
254 array(PropertyNormalizer::GROUPS => array('a', 'b'))
256 $this->assertEquals($obj, $normalized);
259 public function testGroupsNormalizeWithNameConverter()
261 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
262 $this->normalizer = new PropertyNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
263 $this->normalizer->setSerializer($this->serializer);
265 $obj = new GroupDummy();
266 $obj->setFooBar('@dunglas');
267 $obj->setSymfony('@coopTilleuls');
268 $obj->setCoopTilleuls('les-tilleuls.coop');
273 'foo_bar' => '@dunglas',
274 'symfony' => '@coopTilleuls',
276 $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('name_converter')))
280 public function testGroupsDenormalizeWithNameConverter()
282 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
283 $this->normalizer = new PropertyNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
284 $this->normalizer->setSerializer($this->serializer);
286 $obj = new GroupDummy();
287 $obj->setFooBar('@dunglas');
288 $obj->setSymfony('@coopTilleuls');
292 $this->normalizer->denormalize(array(
294 'foo_bar' => '@dunglas',
295 'symfony' => '@coopTilleuls',
296 'coop_tilleuls' => 'les-tilleuls.coop',
297 ), 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy', null, array(PropertyNormalizer::GROUPS => array('name_converter')))
301 public function provideCallbacks()
306 'bar' => function ($bar) {
311 array('foo' => '', 'bar' => 'baz'),
316 'bar' => function ($bar) {
321 array('foo' => '', 'bar' => null),
326 'bar' => function ($bar) {
327 return $bar->format('d-m-Y H:i:s');
330 new \DateTime('2011-09-10 06:30:00'),
331 array('foo' => '', 'bar' => '10-09-2011 06:30:00'),
336 'bar' => function ($bars) {
338 foreach ($bars as $bar) {
339 $foos .= $bar->getFoo();
345 array(new PropertyConstructorDummy('baz', ''), new PropertyConstructorDummy('quux', '')),
346 array('foo' => '', 'bar' => 'bazquux'),
347 'Collect a property',
351 'bar' => function ($bars) {
355 array(new PropertyConstructorDummy('baz', ''), new PropertyConstructorDummy('quux', '')),
356 array('foo' => '', 'bar' => 2),
363 * @expectedException \Symfony\Component\Serializer\Exception\CircularReferenceException
365 public function testUnableToNormalizeCircularReference()
367 $serializer = new Serializer(array($this->normalizer));
368 $this->normalizer->setSerializer($serializer);
369 $this->normalizer->setCircularReferenceLimit(2);
371 $obj = new PropertyCircularReferenceDummy();
373 $this->normalizer->normalize($obj);
376 public function testSiblingReference()
378 $serializer = new Serializer(array($this->normalizer));
379 $this->normalizer->setSerializer($serializer);
381 $siblingHolder = new PropertySiblingHolder();
384 'sibling0' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
385 'sibling1' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
386 'sibling2' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
388 $this->assertEquals($expected, $this->normalizer->normalize($siblingHolder));
391 public function testCircularReferenceHandler()
393 $serializer = new Serializer(array($this->normalizer));
394 $this->normalizer->setSerializer($serializer);
395 $this->normalizer->setCircularReferenceHandler(function ($obj) {
396 return get_class($obj);
399 $obj = new PropertyCircularReferenceDummy();
401 $expected = array('me' => 'Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy');
402 $this->assertEquals($expected, $this->normalizer->normalize($obj));
405 public function testDenormalizeNonExistingAttribute()
409 $this->normalizer->denormalize(array('non_existing' => true), __NAMESPACE__.'\PropertyDummy')
413 public function testDenormalizeShouldIgnoreStaticProperty()
415 $obj = $this->normalizer->denormalize(array('outOfScope' => true), __NAMESPACE__.'\PropertyDummy');
417 $this->assertEquals(new PropertyDummy(), $obj);
418 $this->assertEquals('out_of_scope', PropertyDummy::$outOfScope);
422 * @expectedException \Symfony\Component\Serializer\Exception\LogicException
423 * @expectedExceptionMessage Cannot normalize attribute "bar" because injected serializer is not a normalizer
425 public function testUnableToNormalizeObjectAttribute()
427 $serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
428 $this->normalizer->setSerializer($serializer);
430 $obj = new PropertyDummy();
431 $object = new \stdClass();
432 $obj->setBar($object);
434 $this->normalizer->normalize($obj, 'any');
437 public function testNoTraversableSupport()
439 $this->assertFalse($this->normalizer->supportsNormalization(new \ArrayObject()));
442 public function testNoStaticPropertySupport()
444 $this->assertFalse($this->normalizer->supportsNormalization(new StaticPropertyDummy()));
450 public static $outOfScope = 'out_of_scope';
453 protected $camelCase;
455 public function getBar()
460 public function setBar($bar)
465 public function getCamelCase()
467 return $this->camelCase;
470 public function setCamelCase($camelCase)
472 $this->camelCase = $camelCase;
476 class PropertyConstructorDummy
481 public function __construct($foo, $bar)
487 public function getFoo()
492 public function getBar()
498 class PropertyCamelizedDummy
500 private $kevinDunglas;
504 public function __construct($kevinDunglas = null)
506 $this->kevinDunglas = $kevinDunglas;
510 class StaticPropertyDummy
512 private static $property = 'value';