Created
February 20, 2014 18:46
-
-
Save danscotton/9120521 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Parser | |
{ | |
public function parse($json = null) | |
{ | |
return array_reduce($this->parseItems($json), array($this, 'parseItem'), new Collection()); | |
} | |
private function parseItems($json) | |
{ | |
switch (true) { | |
case $this->invalid($json): | |
throw new InvalidArgumentException('Expected JSON as first parameter to `parse` method.'); | |
break; | |
case $this->unknown($json): | |
throw new ParserError('Expected JSON to have `results` key.'); | |
break; | |
} | |
$results = json_decode($json, true); | |
return $results['results']; | |
} | |
private function parseItem($collection, $item) | |
{ | |
$collection->add(new CreativeWork($item)); | |
return $collection; | |
} | |
private function invalid($json) | |
{ | |
return !is_string($json) || is_null(json_decode($json)); | |
} | |
private function unknown($json) | |
{ | |
return array_key_exists('results', json_decode($json, true)) ? false : true; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class ParserTest extends PHPUnit_Framework_TestCase | |
{ | |
public function setup() | |
{ | |
$this->parser = new Parser(); | |
} | |
public function testParseCreatesCreativeWorkWithItem() | |
{ | |
$item = array("@id" => "http://www.bbc.co.uk/things/1"); | |
$response = $this->results($item); | |
$collection = $this->parser->parse($response); | |
// I need to verify the `CreativeWork` model was instantiated with `$item`. | |
// How can I mock any instance of `CreativeWork` and verify that its constructor was | |
// called with `$item`? I'm thinking along the lines of: | |
// | |
// $mock = Mockery::mock('CreativeWork') | |
// $mock->shouldBeCreatedWith($item) -> this is the verification.. | |
} | |
private function results() | |
{ | |
return json_encode(array('results' => func_get_args())); | |
} | |
} | |
Hi Dan - you can use PHPUnit to verify that the CreativeWork model is instantiated with the right value. It doesn't really matter if you mock the model class or not, you can check before passing $item.
For example:
<?php
class CreativeWork
{
private $item;
public function __construct($item)
{
$this->item = $item;
}
public function getItem()
{
return $this->item;
}
}
class Parser
{
public function parse($json = null)
{
$collection = new ArrayObject();
$items = $this->parseItems($json);
return $this->parseItem($collection, $items[0]);
}
public function parseItems($json)
{
$results = json_decode($json, true);
return $results['results'];
}
public function parseItem($collection, $item)
{
$collection->append(new CreativeWork($item));
return $collection;
}
}
class ParserTest extends PHPUnit_Framework_TestCase
{
public function testParseCreatesCreativeWorkWithItem()
{
$item = array("@id" => "http://www.bbc.co.uk/things/1");
$parser = $this->getMock('Parser', array('parseItem'));
$parser->expects($this->any())
->method('parseItem')
->with($this->anything(), $this->anything())
->will($this->returnCallback(
function() use ($item) {
$args = func_get_args();
// ... some code here ...
$args[0]->append(new CreativeWork($args[1])); // $args[1] === $item
return $args[0]; // return collection
}
));
$json = json_encode(array('results' => array($item)));
$collection = $parser->parse($json);
$this->assertTrue($collection->offsetGet(0) instanceof CreativeWork);
$this->assertTrue($collection->offsetGet(0)->getItem() === $item);
}
}
There are other ways to do this, but verifying the arguments using a callback function is the easiest way to do it.
Give me a shout if you have any questions, I'm on IRC: #news (Federico) and Twitter @fedecarg
Dave - good to see you buddy. Hope all is well :)
Cheers,
Federico
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Right now, it's not possible. You can use the instance mocks, but they're messy as you need to run tests with process isolation, but even then, you can't yet verify how the constructor was called, though I don't think it would be too difficult to add.
If at all possible, I'd just be trying to verify the observable state changes, like