[PropertyAccess] Refactored PropertyAccessorCollectionTest
This commit is contained in:
parent
0488389d95
commit
20e6bf8f49
@ -5,6 +5,9 @@ CHANGELOG
|
|||||||
------
|
------
|
||||||
|
|
||||||
* allowed non alpha numeric characters in second level and deeper object properties names
|
* allowed non alpha numeric characters in second level and deeper object properties names
|
||||||
|
* [BC BREAK] when accessing an index on an object that does not implement
|
||||||
|
ArrayAccess, a NoSuchIndexException is now thrown instead of the
|
||||||
|
semantically wrong NoSuchPropertyException
|
||||||
|
|
||||||
2.3.0
|
2.3.0
|
||||||
------
|
------
|
||||||
|
@ -160,12 +160,12 @@ class PropertyAccessor implements PropertyAccessorInterface
|
|||||||
*
|
*
|
||||||
* @return mixed The value of the key
|
* @return mixed The value of the key
|
||||||
*
|
*
|
||||||
* @throws NoSuchPropertyException If the array does not implement \ArrayAccess or it is not an array
|
* @throws NoSuchIndexException If the array does not implement \ArrayAccess or it is not an array
|
||||||
*/
|
*/
|
||||||
private function &readIndex(&$array, $index)
|
private function &readIndex(&$array, $index)
|
||||||
{
|
{
|
||||||
if (!$array instanceof \ArrayAccess && !is_array($array)) {
|
if (!$array instanceof \ArrayAccess && !is_array($array)) {
|
||||||
throw new NoSuchPropertyException(sprintf('Index "%s" cannot be read from object of type "%s" because it doesn\'t implement \ArrayAccess', $index, get_class($array)));
|
throw new NoSuchIndexException(sprintf('Index "%s" cannot be read from object of type "%s" because it doesn\'t implement \ArrayAccess', $index, get_class($array)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use an array instead of an object since performance is very crucial here
|
// Use an array instead of an object since performance is very crucial here
|
||||||
@ -271,12 +271,12 @@ class PropertyAccessor implements PropertyAccessorInterface
|
|||||||
* @param string|integer $index The index to write at
|
* @param string|integer $index The index to write at
|
||||||
* @param mixed $value The value to write
|
* @param mixed $value The value to write
|
||||||
*
|
*
|
||||||
* @throws NoSuchPropertyException If the array does not implement \ArrayAccess or it is not an array
|
* @throws NoSuchIndexException If the array does not implement \ArrayAccess or it is not an array
|
||||||
*/
|
*/
|
||||||
private function writeIndex(&$array, $index, $value)
|
private function writeIndex(&$array, $index, $value)
|
||||||
{
|
{
|
||||||
if (!$array instanceof \ArrayAccess && !is_array($array)) {
|
if (!$array instanceof \ArrayAccess && !is_array($array)) {
|
||||||
throw new NoSuchPropertyException(sprintf('Index "%s" cannot be modified in object of type "%s" because it doesn\'t implement \ArrayAccess', $index, get_class($array)));
|
throw new NoSuchIndexException(sprintf('Index "%s" cannot be modified in object of type "%s" because it doesn\'t implement \ArrayAccess', $index, get_class($array)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$array[$index] = $value;
|
$array[$index] = $value;
|
||||||
|
@ -47,19 +47,6 @@ class PropertyAccessorCollectionTest_Car
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PropertyAccessorCollectionTest_CarCustomSingular
|
|
||||||
{
|
|
||||||
public function addFoo($axis) {}
|
|
||||||
|
|
||||||
public function removeFoo($axis) {}
|
|
||||||
|
|
||||||
public function getAxes() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PropertyAccessorCollectionTest_Engine
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
class PropertyAccessorCollectionTest_CarOnlyAdder
|
class PropertyAccessorCollectionTest_CarOnlyAdder
|
||||||
{
|
{
|
||||||
public function addAxis($axis) {}
|
public function addAxis($axis) {}
|
||||||
@ -79,13 +66,6 @@ class PropertyAccessorCollectionTest_CarNoAdderAndRemover
|
|||||||
public function getAxes() {}
|
public function getAxes() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PropertyAccessorCollectionTest_CarNoAdderAndRemoverWithProperty
|
|
||||||
{
|
|
||||||
protected $axes = array();
|
|
||||||
|
|
||||||
public function getAxes() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PropertyAccessorCollectionTest_CompositeCar
|
class PropertyAccessorCollectionTest_CompositeCar
|
||||||
{
|
{
|
||||||
public function getStructure() {}
|
public function getStructure() {}
|
||||||
@ -116,52 +96,34 @@ abstract class PropertyAccessorCollectionTest extends \PHPUnit_Framework_TestCas
|
|||||||
|
|
||||||
abstract protected function getCollection(array $array);
|
abstract protected function getCollection(array $array);
|
||||||
|
|
||||||
public function testGetValueReadsArrayAccess()
|
public function getValidPropertyPaths()
|
||||||
{
|
{
|
||||||
$object = $this->getCollection(array('firstName' => 'Bernhard'));
|
return array(
|
||||||
|
array(array('firstName' => 'Bernhard'), '[firstName]', 'Bernhard'),
|
||||||
$this->assertEquals('Bernhard', $this->propertyAccessor->getValue($object, '[firstName]'));
|
array(array('person' => array('firstName' => 'Bernhard')), '[person][firstName]', 'Bernhard'),
|
||||||
}
|
);
|
||||||
|
|
||||||
public function testGetValueReadsNestedArrayAccess()
|
|
||||||
{
|
|
||||||
$object = $this->getCollection(array('person' => array('firstName' => 'Bernhard')));
|
|
||||||
|
|
||||||
$this->assertEquals('Bernhard', $this->propertyAccessor->getValue($object, '[person][firstName]'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
|
* @dataProvider getValidPropertyPaths
|
||||||
*/
|
*/
|
||||||
public function testGetValueThrowsExceptionIfArrayAccessExpected()
|
public function testGetValue(array $array, $path, $value)
|
||||||
{
|
{
|
||||||
$this->propertyAccessor->getValue(new \stdClass(), '[firstName]');
|
$collection = $this->getCollection($array);
|
||||||
}
|
|
||||||
|
|
||||||
public function testSetValueUpdatesArrayAccess()
|
$this->assertSame($value, $this->propertyAccessor->getValue($collection, $path));
|
||||||
{
|
|
||||||
$object = $this->getCollection(array());
|
|
||||||
|
|
||||||
$this->propertyAccessor->setValue($object, '[firstName]', 'Bernhard');
|
|
||||||
|
|
||||||
$this->assertEquals('Bernhard', $object['firstName']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSetValueUpdatesNestedArrayAccess()
|
|
||||||
{
|
|
||||||
$object = $this->getCollection(array());
|
|
||||||
|
|
||||||
$this->propertyAccessor->setValue($object, '[person][firstName]', 'Bernhard');
|
|
||||||
|
|
||||||
$this->assertEquals('Bernhard', $object['person']['firstName']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
|
* @dataProvider getValidPropertyPaths
|
||||||
*/
|
*/
|
||||||
public function testSetValueThrowsExceptionIfArrayAccessExpected()
|
public function testSetValue(array $array, $path)
|
||||||
{
|
{
|
||||||
$this->propertyAccessor->setValue(new \stdClass(), '[firstName]', 'Bernhard');
|
$collection = $this->getCollection($array);
|
||||||
|
|
||||||
|
$this->propertyAccessor->setValue($collection, $path, 'Updated');
|
||||||
|
|
||||||
|
$this->assertSame('Updated', $this->propertyAccessor->getValue($collection, $path));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetValueCallsAdderAndRemoverForCollections()
|
public function testSetValueCallsAdderAndRemoverForCollections()
|
||||||
@ -210,32 +172,9 @@ abstract class PropertyAccessorCollectionTest extends \PHPUnit_Framework_TestCas
|
|||||||
$this->propertyAccessor->setValue($car, 'structure.axes', $axesAfter);
|
$this->propertyAccessor->setValue($car, 'structure.axes', $axesAfter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetValueCallsCustomAdderAndRemover()
|
|
||||||
{
|
|
||||||
$this->markTestSkipped('This feature is temporarily disabled as of 2.1');
|
|
||||||
|
|
||||||
$car = $this->getMock(__CLASS__.'_CarCustomSingular');
|
|
||||||
$axesBefore = $this->getCollection(array(1 => 'second', 3 => 'fourth'));
|
|
||||||
$axesAfter = $this->getCollection(array(0 => 'first', 1 => 'second', 2 => 'third'));
|
|
||||||
|
|
||||||
$car->expects($this->at(0))
|
|
||||||
->method('getAxes')
|
|
||||||
->will($this->returnValue($axesBefore));
|
|
||||||
$car->expects($this->at(1))
|
|
||||||
->method('removeFoo')
|
|
||||||
->with('fourth');
|
|
||||||
$car->expects($this->at(2))
|
|
||||||
->method('addFoo')
|
|
||||||
->with('first');
|
|
||||||
$car->expects($this->at(3))
|
|
||||||
->method('addFoo')
|
|
||||||
->with('third');
|
|
||||||
|
|
||||||
$this->propertyAccessor->setValue($car, 'axes|foo', $axesAfter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
|
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
|
||||||
|
* @expectedExceptionMessage Found the public method "addAxis()", but did not find a public "removeAxis()" on class Mock_PropertyAccessorCollectionTest_CarOnlyAdder
|
||||||
*/
|
*/
|
||||||
public function testSetValueFailsIfOnlyAdderFound()
|
public function testSetValueFailsIfOnlyAdderFound()
|
||||||
{
|
{
|
||||||
@ -252,6 +191,7 @@ abstract class PropertyAccessorCollectionTest extends \PHPUnit_Framework_TestCas
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
|
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
|
||||||
|
* @expectedExceptionMessage Found the public method "removeAxis()", but did not find a public "addAxis()" on class Mock_PropertyAccessorCollectionTest_CarOnlyRemover
|
||||||
*/
|
*/
|
||||||
public function testSetValueFailsIfOnlyRemoverFound()
|
public function testSetValueFailsIfOnlyRemoverFound()
|
||||||
{
|
{
|
||||||
@ -267,58 +207,14 @@ abstract class PropertyAccessorCollectionTest extends \PHPUnit_Framework_TestCas
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider noAdderRemoverData
|
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
|
||||||
|
* @expectedExceptionMessage Neither the property "axes" nor one of the methods "addAx()", "addAxe()", "addAxis()", "setAxes()", "__set()" or "__call()" exist and have public access in class "Mock_PropertyAccessorCollectionTest_CarNoAdderAndRemover
|
||||||
*/
|
*/
|
||||||
public function testNoAdderAndRemoverThrowsSensibleError($car, $path, $message)
|
public function testSetValueFailsIfNoAdderAndNoRemoverFound()
|
||||||
{
|
{
|
||||||
|
$car = $this->getMock(__CLASS__.'_CarNoAdderAndRemover');
|
||||||
$axes = $this->getCollection(array(0 => 'first', 1 => 'second', 2 => 'third'));
|
$axes = $this->getCollection(array(0 => 'first', 1 => 'second', 2 => 'third'));
|
||||||
|
|
||||||
try {
|
$this->propertyAccessor->setValue($car, 'axes', $axes);
|
||||||
$this->propertyAccessor->setValue($car, $path, $axes);
|
|
||||||
$this->fail('An expected exception was not thrown!');
|
|
||||||
} catch (ExceptionInterface $e) {
|
|
||||||
$this->assertEquals($message, $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function noAdderRemoverData()
|
|
||||||
{
|
|
||||||
$data = array();
|
|
||||||
|
|
||||||
$car = $this->getMock(__CLASS__.'_CarNoAdderAndRemover');
|
|
||||||
$propertyPath = 'axes';
|
|
||||||
$expectedMessage = sprintf(
|
|
||||||
'Neither the property "axes" nor one of the methods "addAx()", '.
|
|
||||||
'"addAxe()", "addAxis()", "setAxes()", "__set()" or "__call()" exist and have '.
|
|
||||||
'public access in class "%s".',
|
|
||||||
get_class($car)
|
|
||||||
);
|
|
||||||
$data[] = array($car, $propertyPath, $expectedMessage);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Temporarily disabled in 2.1
|
|
||||||
|
|
||||||
$propertyPath = new PropertyPath('axes|boo');
|
|
||||||
$expectedMessage = sprintf(
|
|
||||||
'Neither element "axes" nor method "setAxes()" exists in class '
|
|
||||||
.'"%s", nor could adders and removers be found based on the '
|
|
||||||
.'passed singular: %s',
|
|
||||||
get_class($car),
|
|
||||||
'boo'
|
|
||||||
);
|
|
||||||
$data[] = array($car, $propertyPath, $expectedMessage);
|
|
||||||
*/
|
|
||||||
|
|
||||||
$car = $this->getMock(__CLASS__.'_CarNoAdderAndRemoverWithProperty');
|
|
||||||
$propertyPath = 'axes';
|
|
||||||
$expectedMessage = sprintf(
|
|
||||||
'Neither the property "axes" nor one of the methods "addAx()", '.
|
|
||||||
'"addAxe()", "addAxis()", "setAxes()", "__set()" or "__call()" exist and have '.
|
|
||||||
'public access in class "%s".',
|
|
||||||
get_class($car)
|
|
||||||
);
|
|
||||||
$data[] = array($car, $propertyPath, $expectedMessage);
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function getValidPropertyPaths()
|
public function getValidPropertyPaths()
|
||||||
{
|
{
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
array(array('Bernhard', 'Schussek'), '[0]', 'Bernhard'),
|
array(array('Bernhard', 'Schussek'), '[0]', 'Bernhard'),
|
||||||
array(array('Bernhard', 'Schussek'), '[1]', 'Schussek'),
|
array(array('Bernhard', 'Schussek'), '[1]', 'Schussek'),
|
||||||
@ -65,7 +64,6 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function getPathsWithMissingProperty()
|
public function getPathsWithMissingProperty()
|
||||||
{
|
{
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
array((object) array('firstName' => 'Bernhard'), 'lastName'),
|
array((object) array('firstName' => 'Bernhard'), 'lastName'),
|
||||||
array((object) array('property' => (object) array('firstName' => 'Bernhard')), 'property.lastName'),
|
array((object) array('property' => (object) array('firstName' => 'Bernhard')), 'property.lastName'),
|
||||||
@ -86,7 +84,6 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function getPathsWithMissingIndex()
|
public function getPathsWithMissingIndex()
|
||||||
{
|
{
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
array(array('firstName' => 'Bernhard'), '[lastName]'),
|
array(array('firstName' => 'Bernhard'), '[lastName]'),
|
||||||
array(array(), '[index][lastName]'),
|
array(array(), '[index][lastName]'),
|
||||||
@ -131,6 +128,14 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->propertyAccessor->getValue($objectOrArray, $path);
|
$this->propertyAccessor->getValue($objectOrArray, $path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchIndexException
|
||||||
|
*/
|
||||||
|
public function testGetValueThrowsExceptionIfNotArrayAccess()
|
||||||
|
{
|
||||||
|
$this->propertyAccessor->getValue(new \stdClass(), '[index]');
|
||||||
|
}
|
||||||
|
|
||||||
public function testGetValueReadsMagicGet()
|
public function testGetValueReadsMagicGet()
|
||||||
{
|
{
|
||||||
$this->assertSame('Bernhard', $this->propertyAccessor->getValue(new TestClassMagicGet('Bernhard'), 'magicProperty'));
|
$this->assertSame('Bernhard', $this->propertyAccessor->getValue(new TestClassMagicGet('Bernhard'), 'magicProperty'));
|
||||||
@ -229,6 +234,14 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertSame('Updated', $this->propertyAccessor->getValue($objectOrArray, $path));
|
$this->assertSame('Updated', $this->propertyAccessor->getValue($objectOrArray, $path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchIndexException
|
||||||
|
*/
|
||||||
|
public function testSetValueThrowsExceptionIfNotArrayAccess()
|
||||||
|
{
|
||||||
|
$this->propertyAccessor->setValue(new \stdClass(), '[index]', 'Updated');
|
||||||
|
}
|
||||||
|
|
||||||
public function testSetValueUpdatesMagicSet()
|
public function testSetValueUpdatesMagicSet()
|
||||||
{
|
{
|
||||||
$author = new TestClassMagicGet('Bernhard');
|
$author = new TestClassMagicGet('Bernhard');
|
||||||
|
Reference in New Issue
Block a user