[PropertyAccess] Refactored PropertyAccessorCollectionTest

This commit is contained in:
Bernhard Schussek 2014-03-28 17:07:20 +01:00
parent 0488389d95
commit 20e6bf8f49
4 changed files with 46 additions and 134 deletions

View File

@ -5,6 +5,9 @@ CHANGELOG
------
* 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
------

View File

@ -160,12 +160,12 @@ class PropertyAccessor implements PropertyAccessorInterface
*
* @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)
{
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
@ -271,12 +271,12 @@ class PropertyAccessor implements PropertyAccessorInterface
* @param string|integer $index The index to write at
* @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)
{
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;

View File

@ -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
{
public function addAxis($axis) {}
@ -79,13 +66,6 @@ class PropertyAccessorCollectionTest_CarNoAdderAndRemover
public function getAxes() {}
}
class PropertyAccessorCollectionTest_CarNoAdderAndRemoverWithProperty
{
protected $axes = array();
public function getAxes() {}
}
class PropertyAccessorCollectionTest_CompositeCar
{
public function getStructure() {}
@ -116,52 +96,34 @@ abstract class PropertyAccessorCollectionTest extends \PHPUnit_Framework_TestCas
abstract protected function getCollection(array $array);
public function testGetValueReadsArrayAccess()
public function getValidPropertyPaths()
{
$object = $this->getCollection(array('firstName' => 'Bernhard'));
$this->assertEquals('Bernhard', $this->propertyAccessor->getValue($object, '[firstName]'));
}
public function testGetValueReadsNestedArrayAccess()
{
$object = $this->getCollection(array('person' => array('firstName' => 'Bernhard')));
$this->assertEquals('Bernhard', $this->propertyAccessor->getValue($object, '[person][firstName]'));
return array(
array(array('firstName' => 'Bernhard'), '[firstName]', 'Bernhard'),
array(array('person' => array('firstName' => 'Bernhard')), '[person][firstName]', 'Bernhard'),
);
}
/**
* @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()
{
$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']);
$this->assertSame($value, $this->propertyAccessor->getValue($collection, $path));
}
/**
* @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()
@ -210,32 +172,9 @@ abstract class PropertyAccessorCollectionTest extends \PHPUnit_Framework_TestCas
$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
* @expectedExceptionMessage Found the public method "addAxis()", but did not find a public "removeAxis()" on class Mock_PropertyAccessorCollectionTest_CarOnlyAdder
*/
public function testSetValueFailsIfOnlyAdderFound()
{
@ -252,6 +191,7 @@ abstract class PropertyAccessorCollectionTest extends \PHPUnit_Framework_TestCas
/**
* @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()
{
@ -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'));
try {
$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;
$this->propertyAccessor->setValue($car, 'axes', $axes);
}
}

View File

@ -31,7 +31,6 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
public function getValidPropertyPaths()
{
return array(
array(array('Bernhard', 'Schussek'), '[0]', 'Bernhard'),
array(array('Bernhard', 'Schussek'), '[1]', 'Schussek'),
@ -65,7 +64,6 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
public function getPathsWithMissingProperty()
{
return array(
array((object) array('firstName' => 'Bernhard'), 'lastName'),
array((object) array('property' => (object) array('firstName' => 'Bernhard')), 'property.lastName'),
@ -86,7 +84,6 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
public function getPathsWithMissingIndex()
{
return array(
array(array('firstName' => 'Bernhard'), '[lastName]'),
array(array(), '[index][lastName]'),
@ -131,6 +128,14 @@ class PropertyAccessorTest extends \PHPUnit_Framework_TestCase
$this->propertyAccessor->getValue($objectOrArray, $path);
}
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchIndexException
*/
public function testGetValueThrowsExceptionIfNotArrayAccess()
{
$this->propertyAccessor->getValue(new \stdClass(), '[index]');
}
public function testGetValueReadsMagicGet()
{
$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));
}
/**
* @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchIndexException
*/
public function testSetValueThrowsExceptionIfNotArrayAccess()
{
$this->propertyAccessor->setValue(new \stdClass(), '[index]', 'Updated');
}
public function testSetValueUpdatesMagicSet()
{
$author = new TestClassMagicGet('Bernhard');