How to be a good Apprentice: PHPSpec Pimple Part II

So today I solved a couple of problems and got this running much better yet still incomplete. However notice the new details, it feels like one is learning the way things should be done with the tool more and more and return from the hacky way to the phpspec way.

<?php
 
namespace spec;
 
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use ReflectionFunction;
 
class PimpleSpec extends ObjectBehavior
{
    function it_is_initializable_and_implements_array_access()
    {
        $this->shouldHaveType('Pimple');
        $this->shouldImplement('ArrayAccess');
    }
 
    function it_stores_strings()
    {
        $this['param'] = 'value';
 
        $this['param']->shouldReturn('value');
    }
 
    function it_stores_executable_closures()
    {
        $this['service'] = function() { return new \SplObjectStorage(); };
 
        $this->trueOffsetGet('service')->shouldHaveType('SplObjectStorage');
    }
 
    function it_nests_an_offsetGet_method_to_avoid_collisions_with_PHPSpec()
    {
        $this['service'] = function() { return new \SplObjectStorage(); };
 
        $this->offsetGet('service')->shouldBeLike($this->trueOffsetGet('service'));
    }
 
    function it_executes_with_container_argument_when_value_is_a_factory()
    {
        $this['container'] = function($container) { return $container; };
 
        $this->executeFactory('container')->shouldReturn($this);
    }
 
    public function it_responds_to_isset()
    {
        $this['param'] = 'value';
        $this['service'] = function () { return new \SplObjectStorage(); };
        $this['null'] = null;
 
        $this->shouldHaveKey('param');
        $this->shouldHaveKey('service');
        $this->shouldHaveKey('null');
        $this->shouldNotHaveKey('non_existent');
    }
 
    public function getMatchers()
    {
        return [
            'beAClosure' => function($subject, $closure) {
                $rf = new ReflectionFunction($closure);
                $result = call_user_func($closure) === call_user_func($subject);
                return $rf->isClosure() && $result;
            },
            'returnWhenInvokedWith' => function($subject, array $resultAndArgument) {
                return $resultAndArgument[0] === call_user_func($subject, $resultAndArgument[1]);
            }
        ];
    }
}

Some things to notice is I needed less custom matchers than at the beginning. I am leaving them here just for reference and to grow a library.

Also to be noticed is the fact that I use a wrapper method for the offsetGet because ObjectBehavior object is an ArrayAccess as well.

<?php
 
class Pimple implements ArrayAccess
{
    protected $collection = [];
 
    public function offsetSet($offset, $value)
    {
        $this->collection[$offset] = $value;
    }
 
    public function offsetUnset($offset)
    {
 
    }
 
    public function offsetExists($offset)
    {
        return array_key_exists($offset, $this->collection);
    }
 
    public function offsetGet($offset)
    {
        return $this->trueOffsetGet($offset);
    }
 
    public function trueOffsetGet($offset)
    {
        if (is_object($this->collection[$offset]) && method_exists($this->collection[$offset], '__invoke')) {
            return $this->executeFactory($offset);
        }
 
        return $this->collection[$offset];
    }
 
    public function executeFactory($offset)
    {
        return $this->collection[$offset]($this);
    }
}

Encouragements in all good!

2 thoughts on “How to be a good Apprentice: PHPSpec Pimple Part II

  1. Pingback: Porting your PHPUnit legacy test suite to PhpSpec Adventures: Part VI | Craft It Online!

Leave a Reply to Diego Oliveira Cancel reply

Your email address will not be published. Required fields are marked *