My objective is to ensure that an object graph has expected values and types. I want to ensure every value is of the expected type.
To this end, assertEquals()
is unfortunately not useful:
$this->assertEquals(
[ 'prop' => '0' ],
[ 'prop' => 0 ]
);
// -> no failures
In this case, assertSame()
works nicely:
$this->assertSame(
[ 'prop' => '0' ],
[ 'prop' => 0 ]
);
// Failed asserting that Array &0 (
// 'prop' => 0
// ) is identical to Array &0 (
// 'prop' => '0'
// ).
The problem with assertSame()
is that it also checks reference for objects:
$this->assertSame(
(object) [ 'prop' => 0 ],
(object) [ 'prop' => 0 ]
);
// Failed asserting that two variables reference the same object.
What options do I have?
On a separate note, I'm not sure why this was designed in this way - to me it feels that assertSame()
does two things at once (I've have at most verified object class, not references).
So far, I came up with the following option:
/**
* @param mixed $expected
* @param mixed $actual
* @param string $message
*/
public function assertObjectGraph($expected, $actual, $message = '')
{
$expected = $this->convertObjectsToHashes($expected);
$actual = $this->convertObjectsToHashes($actual);
$this->assertSame($expected, $actual, $message);
}
/**
* @param mixed $value
* @return mixed
*/
private function convertObjectsToHashes($value)
{
if (is_object($value)) {
$value = ['__CLASS__' => get_class($value)] + get_object_vars($value);
}
if (is_array($value)) {
$value = array_map([$this, __FUNCTION__], $value);
}
return $value;
}
Examples:
$this->assertObjectGraph(
(object) [ 'prop' => 0 ],
(object) [ 'prop' => 0 ]
);
// -> ok
$this->assertObjectGraph(
(object) [ 'prop' => 0 ],
(object) [ 'prop' => '0' ],
);
// Failed asserting that Array &0 (
// '__CLASS__' => 'stdClass'
// 'prop' => '0'
// ) is identical to Array &0 (
// '__CLASS__' => 'stdClass'
// 'prop' => 0
// ).
class Test{public $prop = 0;}
$this->assertObjectGraph(
(object) [ 'prop' => 0 ],
new Test()
);
// Failed asserting that Array &0 (
// '__CLASS__' => 'Test'
// 'prop' => 0
// ) is identical to Array &0 (
// '__CLASS__' => 'stdClass'
// 'prop' => 0
// ).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With