Skip to content

Instantly share code, notes, and snippets.

@studioromeo
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save studioromeo/9665180 to your computer and use it in GitHub Desktop.
Save studioromeo/9665180 to your computer and use it in GitHub Desktop.
PHPSpec
<?php
namespace Acme;
use Acme\SubDependency;
class Dependency
{
protected $subDep;
function __construct(SubDependency $subDep)
{
$this->subDep = $subDep;
}
function getRender()
{
return $this->subDep->render();
}
}
<?php
namespace Acme;
use Acme\Dependency;
class RoadRunner
{
protected $dep;
public function __construct(Dependency $dep)
{
$this->dep = $dep;
}
public function letsGo()
{
return $this->dep->getRender();
}
}
<?php
namespace spec\Acme;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Acme\Dependency;
use Acme\SubDependency;
class RoadRunnerSpec extends ObjectBehavior
{
function let(Dependency $dependency)
{
// This injects Dependency (subject) into the RoadRunner object but leaves out SubDep from Dependency?
$this->beConstructedWith($dependency)
}
function it_is_initializable()
{
$this->shouldHaveType('Acme\RoadRunner');
}
function it_should_return_dep()
{
// This should return hello world if all dependencies are set up correctly
$this->letsGo()->shouldReturn('Hello World');
}
}
<?php
namespace Acme;
class SubDependency
{
public function render()
{
return 'Hello world';
}
}
@studioromeo
Copy link
Author

Now question is how to get the phpspec to pass by injecting the dependencies

@stevelacey
Copy link

Sounds like you want something along the lines of this? I don't know much more than that though:

<?php

namespace spec\Acme;

...
use Acme\DerpDep;

class RoadRunnerSpec extends ObjectBehavior
{
    ...
    function let($derp)
    {
        $this->beConstructedWith($derp);
    }
}

http://www.phpspec.net/docs/introduction.html#let-and-let-go

@studioromeo
Copy link
Author

That's cool yea I got that far... my issue is getting DerpDep injected into TestDep before injecting that into roadrunner

@studioromeo
Copy link
Author

I did think it could be done by writing...

<?php
...

function let(Dependency $dependency, SubDependency $subdep)
{
    $dependency->beConstructedWith([$subdep]);
    $this->beConstructedWith($dependency)
}

But this throws a typecasting error because the object is actually of the type PhpSpec\Wrapper\Collaborator.

So we can get the wrapped object by calling getWrappedObject() like so

<?php
...

function let(Dependency $dependency, SubDependency $subdep)
{
    $dependency->beConstructedWith([$subdep->getWrappedObject()]);
    $this->beConstructedWith($dependency)
}

This will fix the error but does not make the test pass so we're back to square 1 again

@stevelacey
Copy link

I don't have much more advice I'm afraid, my experience with PHPSpec was limited to trying to get it working in a DI scenario, which I quickly established couldn't be done easily since it's designed to construct objects itself, so I switched back to PHPUnit, good luck with it if you haven't solved the problem already!

@jakzal
Copy link

jakzal commented Mar 21, 2014

<?php

namespace spec\Acme;

use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Acme\Dependency;
use Acme\SubDependency;

class RoadRunnerSpec extends ObjectBehavior
{
    function let(Dependency $dependency)
    {
        // You don't care about SubDependency here! You only interact with direct collaborator.
        $this->beConstructedWith($dependency)
    }

    function it_is_initializable()
    {
        $this->shouldHaveType('Acme\RoadRunner');
    }

    function it_renders_a_string(Dependency $dependency)
    {
        $dependency->getRender()->willReturn('Hello World');

        // letGo() returns whatever the Dependency returned, 
        // you should spec Dependency::getRender() in the DependencySpec
        $this->letsGo()->shouldReturn('Hello World');
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment