<?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'; | |
} | |
} |
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
That's cool yea I got that far... my issue is getting DerpDep injected into TestDep before injecting that into roadrunner
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
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!
<?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');
}
}
Now question is how to get the phpspec to pass by injecting the dependencies