Skip to content

Commit

Permalink
Better handling of references to inexistent fixtures (nelmio#592)
Browse files Browse the repository at this point in the history
As of now if a reference to an inexistent fixture in a constructor is made, as no object is found for it, the reference resolver will try to instantiate that fixture. However as it is a temporary fixture, it has no class leading to this obscure error:

`Class  does not exist in /path/to/alice/src/Generator/Instantiator/Chainable/NullConstructorInstantiator.php:36`

A solution is to check if this fixture exist when no object is found to thrown an error before trying to generate it.
  • Loading branch information
theofidry authored Oct 30, 2016
1 parent 5725900 commit 9de6f05
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 128 deletions.
37 changes: 37 additions & 0 deletions src/Definition/Fixture/FixtureId.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/*
* This file is part of the Alice package.
*
* (c) Nelmio <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Nelmio\Alice\Definition\Fixture;

use Nelmio\Alice\FixtureIdInterface;

final class FixtureId implements FixtureIdInterface
{
/**
* @var string
*/
private $id;

public function __construct(string $id)
{
$this->id = $id;
}

/**
* @inheritdoc
*/
public function getId(): string
{
return $this->id;
}
}
25 changes: 25 additions & 0 deletions src/FixtureIdInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

/*
* This file is part of the Alice package.
*
* (c) Nelmio <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Nelmio\Alice;

/**
* A fixture is a value object representing an object to be built.
*/
interface FixtureIdInterface
{
/**
* @return string e.g. 'dummy0'. May contain flags e.g. 'dummy (extends base_dummy)' depending of the implementation.
*/
public function getId(): string;
}
7 changes: 1 addition & 6 deletions src/FixtureInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,8 @@
/**
* A fixture is a value object representing an object to be built.
*/
interface FixtureInterface
interface FixtureInterface extends FixtureIdInterface
{
/**
* @return string e.g. 'dummy0'. May contain flags e.g. 'dummy (extends base_dummy)' depending of the implementation.
*/
public function getId(): string;

/**
* @return string FQCN. May contain flags depending of the implementation.
*/
Expand Down
25 changes: 10 additions & 15 deletions src/Generator/Resolver/Value/Chainable/FixtureReferenceResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@

namespace Nelmio\Alice\Generator\Resolver\Value\Chainable;

use Nelmio\Alice\Definition\Fixture\SimpleFixture;
use Nelmio\Alice\Definition\MethodCallBag;
use Nelmio\Alice\Definition\PropertyBag;
use Nelmio\Alice\Definition\SpecificationBag;
use Nelmio\Alice\Definition\Fixture\FixtureId;
use Nelmio\Alice\Definition\Value\FixtureReferenceValue;
use Nelmio\Alice\Definition\ValueInterface;
use Nelmio\Alice\Exception\FixtureNotFoundException;
use Nelmio\Alice\Exception\Generator\ObjectGenerator\ObjectGeneratorNotFoundException;
use Nelmio\Alice\Exception\Generator\Resolver\UnresolvableValueException;
use Nelmio\Alice\FixtureIdInterface;
use Nelmio\Alice\FixtureInterface;
use Nelmio\Alice\Generator\GenerationContext;
use Nelmio\Alice\Generator\ObjectGeneratorAwareInterface;
Expand Down Expand Up @@ -81,11 +80,15 @@ public function resolve(

$referredFixtureId = $value->getValue();
if ($referredFixtureId instanceof ValueInterface) {
throw new UnresolvableValueException($value);
throw UnresolvableValueException::create($value);
}

$referredFixture = $this->getReferredFixture($referredFixtureId, $fixtureSet);
if (false === $fixtureSet->getObjects()->has($referredFixture)) {
if (false === $referredFixture instanceof FixtureInterface) {
throw FixtureNotFoundException::create($referredFixtureId);
}

$context->markIsResolvingFixture($referredFixtureId);
$objects = $this->generator->generate($referredFixture, $fixtureSet, $context);

Expand All @@ -98,21 +101,13 @@ public function resolve(
);
}

private function getReferredFixture(string $id, ResolvedFixtureSet $set): FixtureInterface
private function getReferredFixture(string $id, ResolvedFixtureSet $set): FixtureIdInterface
{
$fixtures = $set->getFixtures();
if ($fixtures->has($id)) {
return $fixtures->get($id);
}

return new SimpleFixture(
$id,
'',
new SpecificationBag(
null,
new PropertyBag(),
new MethodCallBag()
)
);
return new FixtureId($id);
}
}
11 changes: 7 additions & 4 deletions src/ObjectBag.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,25 +97,28 @@ public function mergeWith(self $objects): self
return $clone;
}

public function has(FixtureInterface $fixture): bool
public function has(FixtureIdInterface $fixture): bool
{
return isset($this->objects[$fixture->getId()]);
}

/**
* @param FixtureInterface $fixture
* @param FixtureIdInterface $fixture
*
* @throws ObjectNotFoundException
*
* @return ObjectInterface
*/
public function get(FixtureInterface $fixture): ObjectInterface
public function get(FixtureIdInterface $fixture): ObjectInterface
{
if ($this->has($fixture)) {
return $this->objects[$fixture->getId()];
}

throw ObjectNotFoundException::create($fixture->getId(), $fixture->getClassName());
throw ObjectNotFoundException::create(
$fixture->getId(),
$fixture instanceof FixtureInterface ? $fixture->getClassName() : 'no class given'
);
}

/**
Expand Down
31 changes: 31 additions & 0 deletions tests/Definition/Fixture/FixtureIdTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/*
* This file is part of the Alice package.
*
* (c) Nelmio <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Nelmio\Alice\Definition\Fixture;

use Nelmio\Alice\FixtureIdInterface;

/**
* @covers \Nelmio\Alice\Definition\Fixture\FixtureId
*/
class FixtureIdTest extends \PHPUnit_Framework_TestCase
{
public function testIsAFixtureId()
{
$this->assertTrue(is_a(FixtureId::class, FixtureIdInterface::class, true));
}

public function testAccessor()
{
$id = new FixtureId('foo');
$this->assertEquals('foo', $id->getId());
}
}
6 changes: 6 additions & 0 deletions tests/Definition/Fixture/SimpleFixtureTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@
use Nelmio\Alice\Definition\MethodCall\DummyMethodCall;
use Nelmio\Alice\Definition\SpecificationBagFactory;
use Nelmio\Alice\Exception\NoValueForCurrentException;
use Nelmio\Alice\FixtureIdInterface;
use Nelmio\Alice\FixtureInterface;

/**
* @covers \Nelmio\Alice\Definition\Fixture\SimpleFixture
*/
class SimpleFixtureTest extends \PHPUnit_Framework_TestCase
{
public function testIsAFixtureId()
{
$this->assertTrue(is_a(SimpleFixture::class, FixtureIdInterface::class, true));
}

public function testIsAFixture()
{
$this->assertTrue(is_a(SimpleFixture::class, FixtureInterface::class, true));
Expand Down
Loading

0 comments on commit 9de6f05

Please sign in to comment.