PropertyAccessorTest.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\PropertyAccess\Tests;
  11. use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException;
  12. use Symfony\Component\PropertyAccess\PropertyAccessor;
  13. use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass;
  14. use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicCall;
  15. use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicGet;
  16. use Symfony\Component\PropertyAccess\Tests\Fixtures\Ticket5775Object;
  17. use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassSetValue;
  18. use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassIsWritable;
  19. use Symfony\Component\PropertyAccess\Tests\Fixtures\TypeHinted;
  20. class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
  21. {
  22. /**
  23. * @var PropertyAccessor
  24. */
  25. private $propertyAccessor;
  26. protected function setUp()
  27. {
  28. $this->propertyAccessor = new PropertyAccessor();
  29. }
  30. public function getPathsWithUnexpectedType()
  31. {
  32. return array(
  33. array('', 'foobar'),
  34. array('foo', 'foobar'),
  35. array(null, 'foobar'),
  36. array(123, 'foobar'),
  37. array((object) array('prop' => null), 'prop.foobar'),
  38. array((object) array('prop' => (object) array('subProp' => null)), 'prop.subProp.foobar'),
  39. array(array('index' => null), '[index][foobar]'),
  40. array(array('index' => array('subIndex' => null)), '[index][subIndex][foobar]'),
  41. );
  42. }
  43. public function getPathsWithMissingProperty()
  44. {
  45. return array(
  46. array((object) array('firstName' => 'Bernhard'), 'lastName'),
  47. array((object) array('property' => (object) array('firstName' => 'Bernhard')), 'property.lastName'),
  48. array(array('index' => (object) array('firstName' => 'Bernhard')), '[index].lastName'),
  49. array(new TestClass('Bernhard'), 'protectedProperty'),
  50. array(new TestClass('Bernhard'), 'privateProperty'),
  51. array(new TestClass('Bernhard'), 'protectedAccessor'),
  52. array(new TestClass('Bernhard'), 'protectedIsAccessor'),
  53. array(new TestClass('Bernhard'), 'protectedHasAccessor'),
  54. array(new TestClass('Bernhard'), 'privateAccessor'),
  55. array(new TestClass('Bernhard'), 'privateIsAccessor'),
  56. array(new TestClass('Bernhard'), 'privateHasAccessor'),
  57. // Properties are not camelized
  58. array(new TestClass('Bernhard'), 'public_property'),
  59. );
  60. }
  61. public function getPathsWithMissingIndex()
  62. {
  63. return array(
  64. array(array('firstName' => 'Bernhard'), '[lastName]'),
  65. array(array(), '[index][lastName]'),
  66. array(array('index' => array()), '[index][lastName]'),
  67. array(array('index' => array('firstName' => 'Bernhard')), '[index][lastName]'),
  68. array((object) array('property' => array('firstName' => 'Bernhard')), 'property[lastName]'),
  69. );
  70. }
  71. /**
  72. * @dataProvider getValidPropertyPaths
  73. */
  74. public function testGetValue($objectOrArray, $path, $value)
  75. {
  76. $this->assertSame($value, $this->propertyAccessor->getValue($objectOrArray, $path));
  77. }
  78. /**
  79. * @dataProvider getPathsWithMissingProperty
  80. * @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
  81. */
  82. public function testGetValueThrowsExceptionIfPropertyNotFound($objectOrArray, $path)
  83. {
  84. $this->propertyAccessor->getValue($objectOrArray, $path);
  85. }
  86. /**
  87. * @dataProvider getPathsWithMissingIndex
  88. */
  89. public function testGetValueThrowsNoExceptionIfIndexNotFound($objectOrArray, $path)
  90. {
  91. $this->assertNull($this->propertyAccessor->getValue($objectOrArray, $path));
  92. }
  93. /**
  94. * @dataProvider getPathsWithMissingIndex
  95. * @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchIndexException
  96. */
  97. public function testGetValueThrowsExceptionIfIndexNotFoundAndIndexExceptionsEnabled($objectOrArray, $path)
  98. {
  99. $this->propertyAccessor = new PropertyAccessor(false, true);
  100. $this->propertyAccessor->getValue($objectOrArray, $path);
  101. }
  102. /**
  103. * @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchIndexException
  104. */
  105. public function testGetValueThrowsExceptionIfNotArrayAccess()
  106. {
  107. $this->propertyAccessor->getValue(new \stdClass(), '[index]');
  108. }
  109. public function testGetValueReadsMagicGet()
  110. {
  111. $this->assertSame('Bernhard', $this->propertyAccessor->getValue(new TestClassMagicGet('Bernhard'), 'magicProperty'));
  112. }
  113. public function testGetValueReadsArrayWithMissingIndexForCustomPropertyPath()
  114. {
  115. $object = new \ArrayObject();
  116. $array = array('child' => array('index' => $object));
  117. $this->assertNull($this->propertyAccessor->getValue($array, '[child][index][foo][bar]'));
  118. $this->assertSame(array(), $object->getArrayCopy());
  119. }
  120. // https://github.com/symfony/symfony/pull/4450
  121. public function testGetValueReadsMagicGetThatReturnsConstant()
  122. {
  123. $this->assertSame('constant value', $this->propertyAccessor->getValue(new TestClassMagicGet('Bernhard'), 'constantMagicProperty'));
  124. }
  125. public function testGetValueNotModifyObject()
  126. {
  127. $object = new \stdClass();
  128. $object->firstName = array('Bernhard');
  129. $this->assertNull($this->propertyAccessor->getValue($object, 'firstName[1]'));
  130. $this->assertSame(array('Bernhard'), $object->firstName);
  131. }
  132. public function testGetValueNotModifyObjectException()
  133. {
  134. $propertyAccessor = new PropertyAccessor(false, true);
  135. $object = new \stdClass();
  136. $object->firstName = array('Bernhard');
  137. try {
  138. $propertyAccessor->getValue($object, 'firstName[1]');
  139. } catch (NoSuchIndexException $e) {
  140. }
  141. $this->assertSame(array('Bernhard'), $object->firstName);
  142. }
  143. /**
  144. * @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
  145. */
  146. public function testGetValueDoesNotReadMagicCallByDefault()
  147. {
  148. $this->propertyAccessor->getValue(new TestClassMagicCall('Bernhard'), 'magicCallProperty');
  149. }
  150. public function testGetValueReadsMagicCallIfEnabled()
  151. {
  152. $this->propertyAccessor = new PropertyAccessor(true);
  153. $this->assertSame('Bernhard', $this->propertyAccessor->getValue(new TestClassMagicCall('Bernhard'), 'magicCallProperty'));
  154. }
  155. // https://github.com/symfony/symfony/pull/4450
  156. public function testGetValueReadsMagicCallThatReturnsConstant()
  157. {
  158. $this->propertyAccessor = new PropertyAccessor(true);
  159. $this->assertSame('constant value', $this->propertyAccessor->getValue(new TestClassMagicCall('Bernhard'), 'constantMagicCallProperty'));
  160. }
  161. /**
  162. * @dataProvider getPathsWithUnexpectedType
  163. * @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
  164. * @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on
  165. */
  166. public function testGetValueThrowsExceptionIfNotObjectOrArray($objectOrArray, $path)
  167. {
  168. $this->propertyAccessor->getValue($objectOrArray, $path);
  169. }
  170. /**
  171. * @dataProvider getValidPropertyPaths
  172. */
  173. public function testSetValue($objectOrArray, $path)
  174. {
  175. $this->propertyAccessor->setValue($objectOrArray, $path, 'Updated');
  176. $this->assertSame('Updated', $this->propertyAccessor->getValue($objectOrArray, $path));
  177. }
  178. /**
  179. * @dataProvider getPathsWithMissingProperty
  180. * @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
  181. */
  182. public function testSetValueThrowsExceptionIfPropertyNotFound($objectOrArray, $path)
  183. {
  184. $this->propertyAccessor->setValue($objectOrArray, $path, 'Updated');
  185. }
  186. /**
  187. * @dataProvider getPathsWithMissingIndex
  188. */
  189. public function testSetValueThrowsNoExceptionIfIndexNotFound($objectOrArray, $path)
  190. {
  191. $this->propertyAccessor->setValue($objectOrArray, $path, 'Updated');
  192. $this->assertSame('Updated', $this->propertyAccessor->getValue($objectOrArray, $path));
  193. }
  194. /**
  195. * @dataProvider getPathsWithMissingIndex
  196. */
  197. public function testSetValueThrowsNoExceptionIfIndexNotFoundAndIndexExceptionsEnabled($objectOrArray, $path)
  198. {
  199. $this->propertyAccessor = new PropertyAccessor(false, true);
  200. $this->propertyAccessor->setValue($objectOrArray, $path, 'Updated');
  201. $this->assertSame('Updated', $this->propertyAccessor->getValue($objectOrArray, $path));
  202. }
  203. /**
  204. * @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchIndexException
  205. */
  206. public function testSetValueThrowsExceptionIfNotArrayAccess()
  207. {
  208. $object = new \stdClass();
  209. $this->propertyAccessor->setValue($object, '[index]', 'Updated');
  210. }
  211. public function testSetValueUpdatesMagicSet()
  212. {
  213. $author = new TestClassMagicGet('Bernhard');
  214. $this->propertyAccessor->setValue($author, 'magicProperty', 'Updated');
  215. $this->assertEquals('Updated', $author->__get('magicProperty'));
  216. }
  217. /**
  218. * @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
  219. */
  220. public function testSetValueThrowsExceptionIfThereAreMissingParameters()
  221. {
  222. $object = new TestClass('Bernhard');
  223. $this->propertyAccessor->setValue($object, 'publicAccessorWithMoreRequiredParameters', 'Updated');
  224. }
  225. /**
  226. * @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
  227. */
  228. public function testSetValueDoesNotUpdateMagicCallByDefault()
  229. {
  230. $author = new TestClassMagicCall('Bernhard');
  231. $this->propertyAccessor->setValue($author, 'magicCallProperty', 'Updated');
  232. }
  233. public function testSetValueUpdatesMagicCallIfEnabled()
  234. {
  235. $this->propertyAccessor = new PropertyAccessor(true);
  236. $author = new TestClassMagicCall('Bernhard');
  237. $this->propertyAccessor->setValue($author, 'magicCallProperty', 'Updated');
  238. $this->assertEquals('Updated', $author->__call('getMagicCallProperty', array()));
  239. }
  240. /**
  241. * @dataProvider getPathsWithUnexpectedType
  242. * @expectedException \Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException
  243. * @expectedExceptionMessage PropertyAccessor requires a graph of objects or arrays to operate on
  244. */
  245. public function testSetValueThrowsExceptionIfNotObjectOrArray($objectOrArray, $path)
  246. {
  247. $this->propertyAccessor->setValue($objectOrArray, $path, 'value');
  248. }
  249. public function testGetValueWhenArrayValueIsNull()
  250. {
  251. $this->propertyAccessor = new PropertyAccessor(false, true);
  252. $this->assertNull($this->propertyAccessor->getValue(array('index' => array('nullable' => null)), '[index][nullable]'));
  253. }
  254. /**
  255. * @dataProvider getValidPropertyPaths
  256. */
  257. public function testIsReadable($objectOrArray, $path)
  258. {
  259. $this->assertTrue($this->propertyAccessor->isReadable($objectOrArray, $path));
  260. }
  261. /**
  262. * @dataProvider getPathsWithMissingProperty
  263. */
  264. public function testIsReadableReturnsFalseIfPropertyNotFound($objectOrArray, $path)
  265. {
  266. $this->assertFalse($this->propertyAccessor->isReadable($objectOrArray, $path));
  267. }
  268. /**
  269. * @dataProvider getPathsWithMissingIndex
  270. */
  271. public function testIsReadableReturnsTrueIfIndexNotFound($objectOrArray, $path)
  272. {
  273. // Non-existing indices can be read. In this case, null is returned
  274. $this->assertTrue($this->propertyAccessor->isReadable($objectOrArray, $path));
  275. }
  276. /**
  277. * @dataProvider getPathsWithMissingIndex
  278. */
  279. public function testIsReadableReturnsFalseIfIndexNotFoundAndIndexExceptionsEnabled($objectOrArray, $path)
  280. {
  281. $this->propertyAccessor = new PropertyAccessor(false, true);
  282. // When exceptions are enabled, non-existing indices cannot be read
  283. $this->assertFalse($this->propertyAccessor->isReadable($objectOrArray, $path));
  284. }
  285. public function testIsReadableRecognizesMagicGet()
  286. {
  287. $this->assertTrue($this->propertyAccessor->isReadable(new TestClassMagicGet('Bernhard'), 'magicProperty'));
  288. }
  289. public function testIsReadableDoesNotRecognizeMagicCallByDefault()
  290. {
  291. $this->assertFalse($this->propertyAccessor->isReadable(new TestClassMagicCall('Bernhard'), 'magicCallProperty'));
  292. }
  293. public function testIsReadableRecognizesMagicCallIfEnabled()
  294. {
  295. $this->propertyAccessor = new PropertyAccessor(true);
  296. $this->assertTrue($this->propertyAccessor->isReadable(new TestClassMagicCall('Bernhard'), 'magicCallProperty'));
  297. }
  298. /**
  299. * @dataProvider getPathsWithUnexpectedType
  300. */
  301. public function testIsReadableReturnsFalseIfNotObjectOrArray($objectOrArray, $path)
  302. {
  303. $this->assertFalse($this->propertyAccessor->isReadable($objectOrArray, $path));
  304. }
  305. /**
  306. * @dataProvider getValidPropertyPaths
  307. */
  308. public function testIsWritable($objectOrArray, $path)
  309. {
  310. $this->assertTrue($this->propertyAccessor->isWritable($objectOrArray, $path));
  311. }
  312. /**
  313. * @dataProvider getPathsWithMissingProperty
  314. */
  315. public function testIsWritableReturnsFalseIfPropertyNotFound($objectOrArray, $path)
  316. {
  317. $this->assertFalse($this->propertyAccessor->isWritable($objectOrArray, $path));
  318. }
  319. /**
  320. * @dataProvider getPathsWithMissingIndex
  321. */
  322. public function testIsWritableReturnsTrueIfIndexNotFound($objectOrArray, $path)
  323. {
  324. // Non-existing indices can be written. Arrays are created on-demand.
  325. $this->assertTrue($this->propertyAccessor->isWritable($objectOrArray, $path));
  326. }
  327. /**
  328. * @dataProvider getPathsWithMissingIndex
  329. */
  330. public function testIsWritableReturnsTrueIfIndexNotFoundAndIndexExceptionsEnabled($objectOrArray, $path)
  331. {
  332. $this->propertyAccessor = new PropertyAccessor(false, true);
  333. // Non-existing indices can be written even if exceptions are enabled
  334. $this->assertTrue($this->propertyAccessor->isWritable($objectOrArray, $path));
  335. }
  336. public function testIsWritableRecognizesMagicSet()
  337. {
  338. $this->assertTrue($this->propertyAccessor->isWritable(new TestClassMagicGet('Bernhard'), 'magicProperty'));
  339. }
  340. public function testIsWritableDoesNotRecognizeMagicCallByDefault()
  341. {
  342. $this->assertFalse($this->propertyAccessor->isWritable(new TestClassMagicCall('Bernhard'), 'magicCallProperty'));
  343. }
  344. public function testIsWritableRecognizesMagicCallIfEnabled()
  345. {
  346. $this->propertyAccessor = new PropertyAccessor(true);
  347. $this->assertTrue($this->propertyAccessor->isWritable(new TestClassMagicCall('Bernhard'), 'magicCallProperty'));
  348. }
  349. /**
  350. * @dataProvider getPathsWithUnexpectedType
  351. */
  352. public function testIsWritableReturnsFalseIfNotObjectOrArray($objectOrArray, $path)
  353. {
  354. $this->assertFalse($this->propertyAccessor->isWritable($objectOrArray, $path));
  355. }
  356. public function getValidPropertyPaths()
  357. {
  358. return array(
  359. array(array('Bernhard', 'Schussek'), '[0]', 'Bernhard'),
  360. array(array('Bernhard', 'Schussek'), '[1]', 'Schussek'),
  361. array(array('firstName' => 'Bernhard'), '[firstName]', 'Bernhard'),
  362. array(array('index' => array('firstName' => 'Bernhard')), '[index][firstName]', 'Bernhard'),
  363. array((object) array('firstName' => 'Bernhard'), 'firstName', 'Bernhard'),
  364. array((object) array('property' => array('firstName' => 'Bernhard')), 'property[firstName]', 'Bernhard'),
  365. array(array('index' => (object) array('firstName' => 'Bernhard')), '[index].firstName', 'Bernhard'),
  366. array((object) array('property' => (object) array('firstName' => 'Bernhard')), 'property.firstName', 'Bernhard'),
  367. // Accessor methods
  368. array(new TestClass('Bernhard'), 'publicProperty', 'Bernhard'),
  369. array(new TestClass('Bernhard'), 'publicAccessor', 'Bernhard'),
  370. array(new TestClass('Bernhard'), 'publicAccessorWithDefaultValue', 'Bernhard'),
  371. array(new TestClass('Bernhard'), 'publicAccessorWithRequiredAndDefaultValue', 'Bernhard'),
  372. array(new TestClass('Bernhard'), 'publicIsAccessor', 'Bernhard'),
  373. array(new TestClass('Bernhard'), 'publicHasAccessor', 'Bernhard'),
  374. array(new TestClass('Bernhard'), 'publicGetSetter', 'Bernhard'),
  375. // Methods are camelized
  376. array(new TestClass('Bernhard'), 'public_accessor', 'Bernhard'),
  377. array(new TestClass('Bernhard'), '_public_accessor', 'Bernhard'),
  378. // Missing indices
  379. array(array('index' => array()), '[index][firstName]', null),
  380. array(array('root' => array('index' => array())), '[root][index][firstName]', null),
  381. // Special chars
  382. array(array('%!@$§.' => 'Bernhard'), '[%!@$§.]', 'Bernhard'),
  383. array(array('index' => array('%!@$§.' => 'Bernhard')), '[index][%!@$§.]', 'Bernhard'),
  384. array((object) array('%!@$§' => 'Bernhard'), '%!@$§', 'Bernhard'),
  385. array((object) array('property' => (object) array('%!@$§' => 'Bernhard')), 'property.%!@$§', 'Bernhard'),
  386. // nested objects and arrays
  387. array(array('foo' => new TestClass('bar')), '[foo].publicGetSetter', 'bar'),
  388. array(new TestClass(array('foo' => 'bar')), 'publicGetSetter[foo]', 'bar'),
  389. array(new TestClass(new TestClass('bar')), 'publicGetter.publicGetSetter', 'bar'),
  390. array(new TestClass(array('foo' => new TestClass('bar'))), 'publicGetter[foo].publicGetSetter', 'bar'),
  391. array(new TestClass(new TestClass(new TestClass('bar'))), 'publicGetter.publicGetter.publicGetSetter', 'bar'),
  392. array(new TestClass(array('foo' => array('baz' => new TestClass('bar')))), 'publicGetter[foo][baz].publicGetSetter', 'bar'),
  393. );
  394. }
  395. public function testTicket5755()
  396. {
  397. $object = new Ticket5775Object();
  398. $this->propertyAccessor->setValue($object, 'property', 'foobar');
  399. $this->assertEquals('foobar', $object->getProperty());
  400. }
  401. public function testSetValueDeepWithMagicGetter()
  402. {
  403. $obj = new TestClassMagicGet('foo');
  404. $obj->publicProperty = array('foo' => array('bar' => 'some_value'));
  405. $this->propertyAccessor->setValue($obj, 'publicProperty[foo][bar]', 'Updated');
  406. $this->assertSame('Updated', $obj->publicProperty['foo']['bar']);
  407. }
  408. public function getReferenceChainObjectsForSetValue()
  409. {
  410. return array(
  411. array(array('a' => array('b' => array('c' => 'old-value'))), '[a][b][c]', 'new-value'),
  412. array(new TestClassSetValue(new TestClassSetValue('old-value')), 'value.value', 'new-value'),
  413. array(new TestClassSetValue(array('a' => array('b' => array('c' => new TestClassSetValue('old-value'))))), 'value[a][b][c].value', 'new-value'),
  414. array(new TestClassSetValue(array('a' => array('b' => 'old-value'))), 'value[a][b]', 'new-value'),
  415. array(new \ArrayIterator(array('a' => array('b' => array('c' => 'old-value')))), '[a][b][c]', 'new-value'),
  416. );
  417. }
  418. /**
  419. * @dataProvider getReferenceChainObjectsForSetValue
  420. */
  421. public function testSetValueForReferenceChainIssue($object, $path, $value)
  422. {
  423. $this->propertyAccessor->setValue($object, $path, $value);
  424. $this->assertEquals($value, $this->propertyAccessor->getValue($object, $path));
  425. }
  426. public function getReferenceChainObjectsForIsWritable()
  427. {
  428. return array(
  429. array(new TestClassIsWritable(array('a' => array('b' => 'old-value'))), 'value[a][b]', false),
  430. array(new TestClassIsWritable(new \ArrayIterator(array('a' => array('b' => 'old-value')))), 'value[a][b]', true),
  431. array(new TestClassIsWritable(array('a' => array('b' => array('c' => new TestClassSetValue('old-value'))))), 'value[a][b][c].value', true),
  432. );
  433. }
  434. /**
  435. * @dataProvider getReferenceChainObjectsForIsWritable
  436. */
  437. public function testIsWritableForReferenceChainIssue($object, $path, $value)
  438. {
  439. $this->assertEquals($value, $this->propertyAccessor->isWritable($object, $path));
  440. }
  441. /**
  442. * @expectedException \Symfony\Component\PropertyAccess\Exception\InvalidArgumentException
  443. * @expectedExceptionMessage Expected argument of type "DateTime", "string" given
  444. */
  445. public function testThrowTypeError()
  446. {
  447. $object = new TypeHinted();
  448. $this->propertyAccessor->setValue($object, 'date', 'This is a string, \DateTime expected.');
  449. }
  450. public function testSetTypeHint()
  451. {
  452. $date = new \DateTime();
  453. $object = new TypeHinted();
  454. $this->propertyAccessor->setValue($object, 'date', $date);
  455. $this->assertSame($date, $object->getDate());
  456. }
  457. public function testArrayNotBeeingOverwritten()
  458. {
  459. $value = array('value1' => 'foo', 'value2' => 'bar');
  460. $object = new TestClass($value);
  461. $this->propertyAccessor->setValue($object, 'publicAccessor[value2]', 'baz');
  462. $this->assertSame('baz', $this->propertyAccessor->getValue($object, 'publicAccessor[value2]'));
  463. $this->assertSame(array('value1' => 'foo', 'value2' => 'baz'), $object->getPublicAccessor());
  464. }
  465. }