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\NameConverter\CamelCaseToSnakeCaseNameConverter;
17 use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
18 use Symfony\Component\Serializer\Serializer;
19 use Symfony\Component\Serializer\SerializerInterface;
20 use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
21 use Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy;
22 use Symfony\Component\Serializer\Tests\Fixtures\MaxDepthDummy;
23 use Symfony\Component\Serializer\Tests\Fixtures\SiblingHolder;
24 use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
25 use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
26 use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy;
28 class GetSetMethodNormalizerTest extends TestCase
31 * @var GetSetMethodNormalizer
35 * @var SerializerInterface
39 protected function setUp()
41 $this->serializer = $this->getMockBuilder(__NAMESPACE__.'\SerializerNormalizer')->getMock();
42 $this->normalizer = new GetSetMethodNormalizer();
43 $this->normalizer->setSerializer($this->serializer);
46 public function testInterface()
48 $this->assertInstanceOf('Symfony\Component\Serializer\Normalizer\NormalizerInterface', $this->normalizer);
49 $this->assertInstanceOf('Symfony\Component\Serializer\Normalizer\DenormalizerInterface', $this->normalizer);
52 public function testNormalize()
54 $obj = new GetSetDummy();
55 $object = new \stdClass();
59 $obj->setCamelCase('camelcase');
60 $obj->setObject($object);
63 ->expects($this->once())
65 ->with($object, 'any')
66 ->will($this->returnValue('string_object'))
75 'camelCase' => 'camelcase',
76 'object' => 'string_object',
78 $this->normalizer->normalize($obj, 'any')
82 public function testDenormalize()
84 $obj = $this->normalizer->denormalize(
85 array('foo' => 'foo', 'bar' => 'bar', 'baz' => true, 'fooBar' => 'foobar'),
86 __NAMESPACE__.'\GetSetDummy',
89 $this->assertEquals('foo', $obj->getFoo());
90 $this->assertEquals('bar', $obj->getBar());
91 $this->assertTrue($obj->isBaz());
94 public function testDenormalizeWithObject()
96 $data = new \stdClass();
99 $data->fooBar = 'foobar';
100 $obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\GetSetDummy', 'any');
101 $this->assertEquals('foo', $obj->getFoo());
102 $this->assertEquals('bar', $obj->getBar());
105 public function testDenormalizeNull()
107 $this->assertEquals(new GetSetDummy(), $this->normalizer->denormalize(null, __NAMESPACE__.'\GetSetDummy'));
110 public function testConstructorDenormalize()
112 $obj = $this->normalizer->denormalize(
113 array('foo' => 'foo', 'bar' => 'bar', 'baz' => true, 'fooBar' => 'foobar'),
114 __NAMESPACE__.'\GetConstructorDummy', 'any');
115 $this->assertEquals('foo', $obj->getFoo());
116 $this->assertEquals('bar', $obj->getBar());
117 $this->assertTrue($obj->isBaz());
120 public function testConstructorDenormalizeWithNullArgument()
122 $obj = $this->normalizer->denormalize(
123 array('foo' => 'foo', 'bar' => null, 'baz' => true),
124 __NAMESPACE__.'\GetConstructorDummy', 'any');
125 $this->assertEquals('foo', $obj->getFoo());
126 $this->assertNull($obj->getBar());
127 $this->assertTrue($obj->isBaz());
130 public function testConstructorDenormalizeWithMissingOptionalArgument()
132 $obj = $this->normalizer->denormalize(
133 array('foo' => 'test', 'baz' => array(1, 2, 3)),
134 __NAMESPACE__.'\GetConstructorOptionalArgsDummy', 'any');
135 $this->assertEquals('test', $obj->getFoo());
136 $this->assertEquals(array(), $obj->getBar());
137 $this->assertEquals(array(1, 2, 3), $obj->getBaz());
140 public function testConstructorDenormalizeWithOptionalDefaultArgument()
142 $obj = $this->normalizer->denormalize(
143 array('bar' => 'test'),
144 __NAMESPACE__.'\GetConstructorArgsWithDefaultValueDummy', 'any');
145 $this->assertEquals(array(), $obj->getFoo());
146 $this->assertEquals('test', $obj->getBar());
152 public function testConstructorDenormalizeWithVariadicArgument()
154 $obj = $this->normalizer->denormalize(
155 array('foo' => array(1, 2, 3)),
156 'Symfony\Component\Serializer\Tests\Fixtures\VariadicConstructorArgsDummy', 'any');
157 $this->assertEquals(array(1, 2, 3), $obj->getFoo());
163 public function testConstructorDenormalizeWithMissingVariadicArgument()
165 $obj = $this->normalizer->denormalize(
167 'Symfony\Component\Serializer\Tests\Fixtures\VariadicConstructorArgsDummy', 'any');
168 $this->assertEquals(array(), $obj->getFoo());
171 public function testConstructorWithObjectDenormalize()
173 $data = new \stdClass();
177 $data->fooBar = 'foobar';
178 $obj = $this->normalizer->denormalize($data, __NAMESPACE__.'\GetConstructorDummy', 'any');
179 $this->assertEquals('foo', $obj->getFoo());
180 $this->assertEquals('bar', $obj->getBar());
183 public function testConstructorWArgWithPrivateMutator()
185 $obj = $this->normalizer->denormalize(array('foo' => 'bar'), __NAMESPACE__.'\ObjectConstructorArgsWithPrivateMutatorDummy', 'any');
186 $this->assertEquals('bar', $obj->getFoo());
189 public function testGroupsNormalize()
191 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
192 $this->normalizer = new GetSetMethodNormalizer($classMetadataFactory);
193 $this->normalizer->setSerializer($this->serializer);
195 $obj = new GroupDummy();
198 $obj->setFooBar('fooBar');
199 $obj->setSymfony('symfony');
200 $obj->setKevin('kevin');
201 $obj->setCoopTilleuls('coopTilleuls');
203 $this->assertEquals(array(
205 ), $this->normalizer->normalize($obj, null, array(GetSetMethodNormalizer::GROUPS => array('c'))));
207 $this->assertEquals(array(
208 'symfony' => 'symfony',
210 'fooBar' => 'fooBar',
213 'coopTilleuls' => 'coopTilleuls',
214 ), $this->normalizer->normalize($obj, null, array(GetSetMethodNormalizer::GROUPS => array('a', 'c'))));
217 public function testGroupsDenormalize()
219 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
220 $this->normalizer = new GetSetMethodNormalizer($classMetadataFactory);
221 $this->normalizer->setSerializer($this->serializer);
223 $obj = new GroupDummy();
226 $toNormalize = array('foo' => 'foo', 'bar' => 'bar');
228 $normalized = $this->normalizer->denormalize(
230 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
232 array(GetSetMethodNormalizer::GROUPS => array('a'))
234 $this->assertEquals($obj, $normalized);
238 $normalized = $this->normalizer->denormalize(
240 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy',
242 array(GetSetMethodNormalizer::GROUPS => array('a', 'b'))
244 $this->assertEquals($obj, $normalized);
247 public function testGroupsNormalizeWithNameConverter()
249 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
250 $this->normalizer = new GetSetMethodNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
251 $this->normalizer->setSerializer($this->serializer);
253 $obj = new GroupDummy();
254 $obj->setFooBar('@dunglas');
255 $obj->setSymfony('@coopTilleuls');
256 $obj->setCoopTilleuls('les-tilleuls.coop');
261 'foo_bar' => '@dunglas',
262 'symfony' => '@coopTilleuls',
264 $this->normalizer->normalize($obj, null, array(GetSetMethodNormalizer::GROUPS => array('name_converter')))
268 public function testGroupsDenormalizeWithNameConverter()
270 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
271 $this->normalizer = new GetSetMethodNormalizer($classMetadataFactory, new CamelCaseToSnakeCaseNameConverter());
272 $this->normalizer->setSerializer($this->serializer);
274 $obj = new GroupDummy();
275 $obj->setFooBar('@dunglas');
276 $obj->setSymfony('@coopTilleuls');
280 $this->normalizer->denormalize(array(
282 'foo_bar' => '@dunglas',
283 'symfony' => '@coopTilleuls',
284 'coop_tilleuls' => 'les-tilleuls.coop',
285 ), 'Symfony\Component\Serializer\Tests\Fixtures\GroupDummy', null, array(GetSetMethodNormalizer::GROUPS => array('name_converter')))
290 * @dataProvider provideCallbacks
292 public function testCallbacks($callbacks, $value, $result, $message)
294 $this->normalizer->setCallbacks($callbacks);
296 $obj = new GetConstructorDummy('', $value, true);
300 $this->normalizer->normalize($obj, 'any'),
306 * @expectedException \InvalidArgumentException
308 public function testUncallableCallbacks()
310 $this->normalizer->setCallbacks(array('bar' => null));
312 $obj = new GetConstructorDummy('baz', 'quux', true);
314 $this->normalizer->normalize($obj, 'any');
317 public function testIgnoredAttributes()
319 $this->normalizer->setIgnoredAttributes(array('foo', 'bar', 'baz', 'camelCase', 'object'));
321 $obj = new GetSetDummy();
327 array('fooBar' => 'foobar'),
328 $this->normalizer->normalize($obj, 'any')
332 public function provideCallbacks()
337 'bar' => function ($bar) {
342 array('foo' => '', 'bar' => 'baz', 'baz' => true),
347 'bar' => function ($bar) {
351 array('foo' => '', 'bar' => null, 'baz' => true),
356 'bar' => function ($bar) {
357 return $bar->format('d-m-Y H:i:s');
360 new \DateTime('2011-09-10 06:30:00'),
361 array('foo' => '', 'bar' => '10-09-2011 06:30:00', 'baz' => true),
366 'bar' => function ($bars) {
368 foreach ($bars as $bar) {
369 $foos .= $bar->getFoo();
375 array(new GetConstructorDummy('baz', '', false), new GetConstructorDummy('quux', '', false)),
376 array('foo' => '', 'bar' => 'bazquux', 'baz' => true),
377 'Collect a property',
381 'bar' => function ($bars) {
385 array(new GetConstructorDummy('baz', '', false), new GetConstructorDummy('quux', '', false)),
386 array('foo' => '', 'bar' => 2, 'baz' => true),
393 * @expectedException \Symfony\Component\Serializer\Exception\LogicException
394 * @expectedExceptionMessage Cannot normalize attribute "object" because the injected serializer is not a normalizer
396 public function testUnableToNormalizeObjectAttribute()
398 $serializer = $this->getMockBuilder('Symfony\Component\Serializer\SerializerInterface')->getMock();
399 $this->normalizer->setSerializer($serializer);
401 $obj = new GetSetDummy();
402 $object = new \stdClass();
403 $obj->setObject($object);
405 $this->normalizer->normalize($obj, 'any');
409 * @expectedException \Symfony\Component\Serializer\Exception\CircularReferenceException
411 public function testUnableToNormalizeCircularReference()
413 $serializer = new Serializer(array($this->normalizer));
414 $this->normalizer->setSerializer($serializer);
415 $this->normalizer->setCircularReferenceLimit(2);
417 $obj = new CircularReferenceDummy();
419 $this->normalizer->normalize($obj);
422 public function testSiblingReference()
424 $serializer = new Serializer(array($this->normalizer));
425 $this->normalizer->setSerializer($serializer);
427 $siblingHolder = new SiblingHolder();
430 'sibling0' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
431 'sibling1' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
432 'sibling2' => array('coopTilleuls' => 'Les-Tilleuls.coop'),
434 $this->assertEquals($expected, $this->normalizer->normalize($siblingHolder));
437 public function testCircularReferenceHandler()
439 $serializer = new Serializer(array($this->normalizer));
440 $this->normalizer->setSerializer($serializer);
441 $this->normalizer->setCircularReferenceHandler(function ($obj) {
442 return get_class($obj);
445 $obj = new CircularReferenceDummy();
447 $expected = array('me' => 'Symfony\Component\Serializer\Tests\Fixtures\CircularReferenceDummy');
448 $this->assertEquals($expected, $this->normalizer->normalize($obj));
451 public function testObjectToPopulate()
453 $dummy = new GetSetDummy();
454 $dummy->setFoo('foo');
456 $obj = $this->normalizer->denormalize(
457 array('bar' => 'bar'),
458 __NAMESPACE__.'\GetSetDummy',
460 array(GetSetMethodNormalizer::OBJECT_TO_POPULATE => $dummy)
463 $this->assertEquals($dummy, $obj);
464 $this->assertEquals('foo', $obj->getFoo());
465 $this->assertEquals('bar', $obj->getBar());
468 public function testDenormalizeNonExistingAttribute()
472 $this->normalizer->denormalize(array('non_existing' => true), __NAMESPACE__.'\GetSetDummy')
476 public function testDenormalizeShouldNotSetStaticAttribute()
478 $obj = $this->normalizer->denormalize(array('staticObject' => true), __NAMESPACE__.'\GetSetDummy');
480 $this->assertEquals(new GetSetDummy(), $obj);
481 $this->assertNull(GetSetDummy::getStaticObject());
484 public function testNoTraversableSupport()
486 $this->assertFalse($this->normalizer->supportsNormalization(new \ArrayObject()));
489 public function testNoStaticGetSetSupport()
491 $this->assertFalse($this->normalizer->supportsNormalization(new ObjectWithJustStaticSetterDummy()));
494 public function testPrivateSetter()
496 $obj = $this->normalizer->denormalize(array('foo' => 'foobar'), __NAMESPACE__.'\ObjectWithPrivateSetterDummy');
497 $this->assertEquals('bar', $obj->getFoo());
500 public function testHasGetterDenormalize()
502 $obj = $this->normalizer->denormalize(array('foo' => true), ObjectWithHasGetterDummy::class);
503 $this->assertTrue($obj->hasFoo());
506 public function testHasGetterNormalize()
508 $obj = new ObjectWithHasGetterDummy();
512 array('foo' => true),
513 $this->normalizer->normalize($obj, 'any')
517 public function testMaxDepth()
519 $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
520 $this->normalizer = new GetSetMethodNormalizer($classMetadataFactory);
521 $serializer = new Serializer(array($this->normalizer));
522 $this->normalizer->setSerializer($serializer);
524 $level1 = new MaxDepthDummy();
525 $level1->bar = 'level1';
527 $level2 = new MaxDepthDummy();
528 $level2->bar = 'level2';
529 $level1->child = $level2;
531 $level3 = new MaxDepthDummy();
532 $level3->bar = 'level3';
533 $level2->child = $level3;
535 $level4 = new MaxDepthDummy();
536 $level4->bar = 'level4';
537 $level3->child = $level4;
539 $result = $serializer->normalize($level1, null, array(GetSetMethodNormalizer::ENABLE_MAX_DEPTH => true));
554 $this->assertEquals($expected, $result);
563 protected $camelCase;
565 private static $staticObject;
567 public function getFoo()
572 public function setFoo($foo)
577 public function getBar()
582 public function setBar($bar)
587 public function isBaz()
592 public function setBaz($baz)
597 public function getFooBar()
599 return $this->foo.$this->bar;
602 public function getCamelCase()
604 return $this->camelCase;
607 public function setCamelCase($camelCase)
609 $this->camelCase = $camelCase;
612 public function otherMethod()
614 throw new \RuntimeException('Dummy::otherMethod() should not be called');
617 public function setObject($object)
619 $this->object = $object;
622 public function getObject()
624 return $this->object;
627 public static function getStaticObject()
629 return self::$staticObject;
632 public static function setStaticObject($object)
634 self::$staticObject = $object;
637 protected function getPrivate()
639 throw new \RuntimeException('Dummy::getPrivate() should not be called');
643 class GetConstructorDummy
649 public function __construct($foo, $bar, $baz)
656 public function getFoo()
661 public function getBar()
666 public function isBaz()
671 public function otherMethod()
673 throw new \RuntimeException('Dummy::otherMethod() should not be called');
677 abstract class SerializerNormalizer implements SerializerInterface, NormalizerInterface
681 class GetConstructorOptionalArgsDummy
687 public function __construct($foo, $bar = array(), $baz = array())
694 public function getFoo()
699 public function getBar()
704 public function getBaz()
709 public function otherMethod()
711 throw new \RuntimeException('Dummy::otherMethod() should not be called');
715 class GetConstructorArgsWithDefaultValueDummy
720 public function __construct($foo = array(), $bar)
726 public function getFoo()
731 public function getBar()
736 public function otherMethod()
738 throw new \RuntimeException('Dummy::otherMethod() should not be called');
742 class GetCamelizedDummy
744 private $kevinDunglas;
748 public function __construct($kevinDunglas = null)
750 $this->kevinDunglas = $kevinDunglas;
753 public function getKevinDunglas()
755 return $this->kevinDunglas;
758 public function setFooBar($fooBar)
760 $this->fooBar = $fooBar;
763 public function getFooBar()
765 return $this->fooBar;
768 public function setBar_foo($bar_foo)
770 $this->bar_foo = $bar_foo;
773 public function getBar_foo()
775 return $this->bar_foo;
779 class ObjectConstructorArgsWithPrivateMutatorDummy
783 public function __construct($foo)
788 public function getFoo()
793 private function setFoo($foo)
799 class ObjectWithPrivateSetterDummy
801 private $foo = 'bar';
803 public function getFoo()
808 private function setFoo($foo)
813 class ObjectWithJustStaticSetterDummy
815 private static $foo = 'bar';
817 public static function getFoo()
822 public static function setFoo($foo)
828 class ObjectWithHasGetterDummy
832 public function setFoo($foo)
837 public function hasFoo()