Skip to content

Commit

Permalink
AddIfNotPresentTrait fixes, unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
powturns committed Feb 28, 2016
1 parent fd8ca7b commit 7326ba2
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 5 deletions.
5 changes: 3 additions & 2 deletions composer.json
Expand Up @@ -23,7 +23,8 @@
},

"require-dev": {
"phpunit/phpunit": "~4"
"phpunit/phpunit": "~4",
"phake/phake": "^2.2"
},

"autoload": {
Expand All @@ -43,4 +44,4 @@

"bin": [
]
}
}
57 changes: 54 additions & 3 deletions src/DataFixtures/AddIfNotPresentTrait.php
Expand Up @@ -3,15 +3,40 @@
namespace DoctrineExtensions\DataFixtures;


use BadMethodCallException;
use Doctrine\Common\Persistence\ObjectManager;

/**
* Trait applied to fixtures to make it easy to add an entity to the database only if it does not exist
*/
trait AddIfNotPresentTrait
{

/**
* Set the reference entry identified by $name
* and referenced to managed $object. If $name
* already is set, it throws a
* BadMethodCallException exception
*
* @param string $name
* @param object $object - managed object
* @see Doctrine\Common\DataFixtures\ReferenceRepository::addReference
* @throws BadMethodCallException - if repository already has
* a reference by $name
* @return void
*/
abstract function addReference($name, $object);

/**
* Loads an object using stored reference
* named by $name
*
* @param string $name
* @see Doctrine\Common\DataFixtures\ReferenceRepository::getReference
* @return object
*/
abstract function getReference($name);

/**
* Persists the provided entity to the database if it does not exist.
*
Expand All @@ -33,13 +58,39 @@ protected function _addIfNotPresent($entity, $criteria, $referencePrefix, Object

$existingEntity = $repo->findOneBy($criteria);

if ($existingEntity) {
$this->addReference($referencePrefix . '-' . reset($criteria), $existingEntity);
if (!is_null($existingEntity)) {
$this->safeAddReference($referencePrefix . '-' . reset($criteria), $existingEntity);
return $existingEntity;
}

$manager->persist($entity);
$this->addReference($referencePrefix . '-' . reset($criteria), $entity);
$this->safeAddReference($referencePrefix . '-' . reset($criteria), $entity);
return $entity;
}

/**
* Safely adds the reference.
*
* Checks to see if the reference already exists, and if it does, ensures
* that it matches the object.
*
* @param string $name
* @param object $object - managed object
*/
protected function safeAddReference($name, $object)
{
$existing = $this->getReference($name);

if (is_null($existing)) {
$this->addReference($name, $object);
return;
}

if ($existing !== $object) {
throw new \UnexpectedValueException(
sprintf("New value does not match existing %s reference value.\n".
"Cannot reset reference value one it has been set",
$name));
}
}
}
@@ -0,0 +1,162 @@
<?php

namespace DoctrineExtensions\Test\DataFixtures;

use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\EntityRepository;
use DoctrineExtensions\DataFixtures\AddIfNotPresentTrait;

class AddIfNotPresentTraitTest extends \PHPUnit_Framework_TestCase
{
/**
* Test the case where the object isn't present
*/
public function testAddIfNotPresent()
{
$params = $this->params();
$trait = $this->factory();

$entity = new TestEntity('test-id');
$criteria = ['name'=> 'test'];
$prefix = 'test';

$result = \Phake::makeVisible($trait)->_addIfNotPresent($entity, $criteria, $prefix, $params['object_manager']);

\Phake::verify($trait)->addReference('test-test', $entity);
\Phake::verify($params['object_manager'])->persist($entity);

$this->assertSame($entity, $result);
}

/**
* Verify the behaviour when the object already exists in the
* repository.
*/
public function testAddIfNotPresentExists()
{
$params = $this->params();
$trait = $this->factory();

$existingEntity = new TestEntity('test-id');

//Make the repostiory return an object
\Phake::when($params['repo'])
->findOneBy(\Phake::anyParameters())
->thenReturn($existingEntity);

$entity = new TestEntity('test-id');
$criteria = ['name'=> 'test'];
$prefix = 'test';

$result = \Phake::makeVisible($trait)->_addIfNotPresent($entity, $criteria, $prefix, $params['object_manager']);

\Phake::verify($trait)->addReference('test-test', $entity);
\Phake::verify($params['object_manager'], \Phake::times(0))->persist($entity);

$this->assertNotSame($entity, $result);
$this->assertSame($existingEntity, $result);
}

/**
* Verify the behaviour when the reference already exists
*/
public function testAddIfNotPresentReferenceExists()
{
$params = $this->params();
$trait = $this->factory();

$existingEntity = new TestEntity('test-id');

//Make the repostiory return an object
\Phake::when($params['repo'])
->findOneBy(\Phake::anyParameters())
->thenReturn($existingEntity);

\Phake::when($trait)
->getReference('test-test')
->thenReturn($existingEntity);

$entity = new TestEntity('test-id');
$criteria = ['name'=> 'test'];
$prefix = 'test';

$result = \Phake::makeVisible($trait)->_addIfNotPresent($entity, $criteria, $prefix, $params['object_manager']);

\Phake::verify($trait, \Phake::times(0))->addReference('test-test', $entity);
\Phake::verify($params['object_manager'], \Phake::times(0))->persist($entity);

$this->assertNotSame($entity, $result);
$this->assertSame($existingEntity, $result);
}

/**
* Verify the behaviour when the reference is set to a different
* object than the one returned by the repository.
*
* @expectedException \UnexpectedValueException
* @expectedExceptionMessage New value does not match existing test-test reference value
*/
public function testAddIfNotPresentReferenceExistsNoMatch()
{
$params = $this->params();
$trait = $this->factory();

$existingEntity = new TestEntity('test-id');

//Make the repostiory return an object
\Phake::when($params['repo'])
->findOneBy(\Phake::anyParameters())
->thenReturn($existingEntity);

\Phake::when($trait)
->getReference('test-test')
->thenReturn(new TestEntity('test-id'));

$entity = new TestEntity('test-id');
$criteria = ['name'=> 'test'];
$prefix = 'test';

$result = \Phake::makeVisible($trait)->_addIfNotPresent($entity, $criteria, $prefix, $params['object_manager']);

\Phake::verify($trait, \Phake::times(0))->addReference('test-test', $entity);
\Phake::verify($params['object_manager'], \Phake::times(0))->persist($entity);

$this->assertNotSame($entity, $result);
$this->assertSame($existingEntity, $result);
}

/**
* @return array
*/
public function params() {
$params = [
'object_manager' => \Phake::mock(ObjectManager::class),
'repo' => \Phake::mock(EntityRepository::class)
];

\Phake::when($params['object_manager'])
->getRepository(\Phake::anyParameters())->thenReturn($params['repo']);

return $params;
}

/**
* @return ConcreteAddIfNotPresentTrait|\Phake_IMock
*/
public function factory() {
return \Phake::partialMock(ConcreteAddIfNotPresentTrait::class);
}
}

abstract class ConcreteAddIfNotPresentTrait {
use AddIfNotPresentTrait;
}

class TestEntity {
public $id;

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

0 comments on commit 7326ba2

Please sign in to comment.