Browse files

Implemented the sharing of references for the fixtures

  • Loading branch information...
1 parent 18dbe2a commit 669fb86aa4c3e3676188d351669c2775acfba8cf @l3pp4rd l3pp4rd committed Feb 13, 2011
View
2 .gitignore
@@ -0,0 +1,2 @@
+tests/phpunit.xml
+tests/Doctrine/Tests/Common/DataFixtures/temp/*
View
70 README.md
@@ -49,4 +49,72 @@ Now you can easily execute the fixtures:
If you want to append the fixtures instead of purging before loading then pass false
to the 2nd argument of execute:
- $executor->execute($loader->getFixtures(), true);
+ $executor->execute($loader->getFixtures(), true);
+
+## Sharing objects between fixtures
+
+In case if fixture objects have relations to other fixtures, it is now possible
+to easily add a reference to that object by name and later reference it to form
+a relation. Here is an example fixtures for **Role** and **User** relation
+
+ namespace MyDataFixtures;
+
+ use Doctrine\Common\DataFixtures\AbstractFixture;
+
+ class LoadUserRoleData extends AbstractFixture
+ {
+ public function load($manager)
+ {
+ $adminRole = new Role();
+ $adminRole->setName('admin');
+
+ $anonymousRole = new Role;
+ $anonymousRole->setName('anonymous');
+
+ $manager->persist($adminRole);
+ $manager->persist($anonymousRole);
+ $manager->flush();
+
+ // store reference to admin role for User relation to Role
+ $this->addReference('admin-role', $adminRole);
+ }
+ }
+
+And the **User** data loading fixture:
+
+ namespace MyDataFixtures;
+
+ use Doctrine\Common\DataFixtures\AbstractFixture;
+
+ class LoadUserData extends AbstractFixture
+ {
+ public function load($manager)
+ {
+ $user = new User();
+ $user->setUsername('jwage');
+ $user->setPassword('test');
+ $user->setRole(
+ $this->getReference('admin-role') // load the stored reference
+ );
+
+ $manager->persist($user);
+ $manager->flush();
+
+ // store reference of admin-user for other Fixtures
+ $this->addReference('admin-user', $user);
+ }
+ }
+
+**Notice** that the fixture loading order is important!
+
+## Running the tests:
+
+PHPUnit 3.5 or newer together with Mock_Object package is required.
+To setup and run tests follow these steps:
+
+- go to the root directory of data-fixtures
+- run: **git submodule init**
+- run: **git submodule update**
+- go to tests directory: **cd tests**
+- copy the phpunit config **cp phpunit.dist.xml phpunit.xml**
+- run: **phpunit**
View
10 lib/Doctrine/Common/DataFixtures/Executor/AbstractExecutor.php
@@ -36,6 +36,16 @@ public function __construct($manager)
}
/**
+ * Get reference repository
+ *
+ * @return ReferenceRepository
+ */
+ public function getReferenceRepository()
+ {
+ return $this->referenceRepository;
+ }
+
+ /**
* Sets the Purger instance to use for this exector instance.
*
* @param Purger $purger
View
33 lib/Doctrine/Common/DataFixtures/OrderedFixtureInterface.php
@@ -1,33 +0,0 @@
-<?php
-/*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * This software consists of voluntary contributions made by many individuals
- * and is licensed under the LGPL. For more information, see
- * <http://www.doctrine-project.org>.
- */
-
-namespace Doctrine\Common\DataFixtures;
-
-/**
- * Shared Fixture interface needs to be implemented
- * by fixtures, which needs some references to be shared
- * among other fixture classes in order to maintain
- * relation mapping
- *
- * @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
- */
-interface OrderedFixtureInterface
-{
- public function getOrder();
-}
View
7 lib/Doctrine/Common/DataFixtures/SharedFixtureInterface.php
@@ -30,6 +30,11 @@
* @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
*/
interface SharedFixtureInterface extends FixtureInterface
-{
+{
+ /**
+ * Set the reference repository
+ *
+ * @param ReferenceRepository $referenceRepository
+ */
public function setReferenceRepository(ReferenceRepository $referenceRepository);
}
View
82 tests/Doctrine/Tests/Common/DataFixtures/BaseTest.php
@@ -59,4 +59,86 @@ protected function getMockEntityManager()
$em = EntityManager::create($conn, $config);
return $em;
}
+
+ /**
+ * EntityManager mock object together with
+ * annotation mapping driver
+ *
+ * @return EntityManager
+ */
+ protected function getMockAnnotationReaderEntityManager()
+ {
+ $driver = $this->getMock('Doctrine\DBAL\Driver');
+ $driver->expects($this->once())
+ ->method('getDatabasePlatform')
+ ->will($this->returnValue($this->getMock('Doctrine\DBAL\Platforms\MySqlPlatform')));
+
+ $conn = $this->getMock('Doctrine\DBAL\Connection', array(), array(array(), $driver));
+ $conn->expects($this->once())
+ ->method('getEventManager')
+ ->will($this->returnValue($this->getMock('Doctrine\Common\EventManager')));
+
+ $config = $this->getMock('Doctrine\ORM\Configuration');
+ $config->expects($this->once())
+ ->method('getProxyDir')
+ ->will($this->returnValue('test'));
+
+ $config->expects($this->once())
+ ->method('getProxyNamespace')
+ ->will($this->returnValue('Proxies'));
+
+ $reader = new \Doctrine\Common\Annotations\AnnotationReader();
+ $reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
+ $mappingDriver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver(
+ $reader,
+ __DIR__ . '/TestEntity'
+ );
+
+ $config->expects($this->any())
+ ->method('getMetadataDriverImpl')
+ ->will($this->returnValue($mappingDriver));
+
+ $em = EntityManager::create($conn, $config);
+ return $em;
+ }
+
+ /**
+ * EntityManager mock object together with
+ * annotation mapping driver and pdo_sqlite
+ * database in memory
+ *
+ * @return EntityManager
+ */
+ protected function getMockSqliteEntityManager()
+ {
+ $conn = array(
+ 'driver' => 'pdo_sqlite',
+ 'memory' => true,
+ );
+
+ $config = $this->getMock('Doctrine\ORM\Configuration');
+ $config->expects($this->once())
+ ->method('getProxyDir')
+ ->will($this->returnValue(__DIR__ . '/temp'));
+
+ $config->expects($this->once())
+ ->method('getProxyNamespace')
+ ->will($this->returnValue('Proxy'));
+
+ $config->expects($this->once())
+ ->method('getAutoGenerateProxyClasses')
+ ->will($this->returnValue(true));
+
+ $reader = new \Doctrine\Common\Annotations\AnnotationReader();
+ $reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
+ $mappingDriver = new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader);
+
+ $config->expects($this->any())
+ ->method('getMetadataDriverImpl')
+ ->will($this->returnValue($mappingDriver));
+
+ $evm = $this->getMock('Doctrine\Common\EventManager');
+ $em = EntityManager::create($conn, $config, $evm);
+ return $em;
+ }
}
View
95 tests/Doctrine/Tests/Common/DataFixtures/Executor/ORMExecutorSharedFixtureTest.php
@@ -0,0 +1,95 @@
+<?php
+/*
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.doctrine-project.org>.
+ */
+
+namespace Doctrine\Tests\Common\DataFixtures;
+
+require_once __DIR__.'/../TestInit.php';
+
+use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
+use Doctrine\Common\DataFixtures\Purger\ORMPurger;
+use Doctrine\ORM\Proxy\Proxy;
+
+/**
+ * Test referenced fixture execution
+ *
+ * @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
+ */
+class ORMExecutorSharedFixtureTest extends BaseTest
+{
+ const TEST_ENTITY_ROLE = 'Doctrine\Tests\Common\DataFixtures\TestEntity\Role';
+ const TEST_ENTITY_USER = 'Doctrine\Tests\Common\DataFixtures\TestEntity\User';
+
+ public function testFixtureExecution()
+ {
+ $em = $this->getMockAnnotationReaderEntityManager();
+ $purger = new ORMPurger();
+ $executor = new ORMExecutor($em, $purger);
+
+ $referenceRepository = $executor->getReferenceRepository();
+ $fixture = $this->getMockFixture();
+ $fixture->expects($this->once())
+ ->method('load')
+ ->with($em);
+
+ $fixture->expects($this->once())
+ ->method('setReferenceRepository')
+ ->with($referenceRepository);
+
+ $executor->execute(array($fixture), true);
+ }
+
+ public function testSharedFixtures()
+ {
+ if (!extension_loaded('pdo_sqlite')) {
+ $this->markTestSkipped('Missing pdo_sqlite extension.');
+ }
+
+ $em = $this->getMockSqliteEntityManager();
+ $schemaTool = new \Doctrine\ORM\Tools\SchemaTool($em);
+ $schemaTool->dropSchema(array());
+ $schemaTool->createSchema(array(
+ $em->getClassMetadata(self::TEST_ENTITY_ROLE),
+ $em->getClassMetadata(self::TEST_ENTITY_USER)
+ ));
+
+ $purger = new ORMPurger();
+ $executor = new ORMExecutor($em, $purger);
+
+ $userFixture = new TestFixtures\UserFixture;
+ $roleFixture = new TestFixtures\RoleFixture;
+ $executor->execute(array($roleFixture, $userFixture), true);
+
+ $referenceRepository = $executor->getReferenceRepository();
+ $references = $referenceRepository->getReferences();
+
+ $this->assertEquals(2, count($references));
+ $roleReference = $referenceRepository->getReference('admin-role');
+ $this->assertTrue($roleReference instanceof Proxy);
+ $this->assertEquals('admin', $roleReference->getName());
+
+ $userReference = $referenceRepository->getReference('admin');
+ $this->assertTrue($userReference instanceof Proxy);
+ $this->assertEquals('admin@example.com', $userReference->getEmail());
+ }
+
+ private function getMockFixture()
+ {
+ return $this->getMock('Doctrine\Common\DataFixtures\SharedFixtureInterface');
+ }
+}
View
5 tests/Doctrine/Tests/Common/DataFixtures/Executor/ORMExecutorTest.php
@@ -71,6 +71,11 @@ public function testExecuteTransaction()
$executor->execute(array($fixture), true);
}
+ public function testSharedFixtureExecution()
+ {
+ $em = $this->getMockEntityManager();
+ }
+
private function getMockFixture($em)
{
return $this->getMock('Doctrine\Common\DataFixtures\FixtureInterface');
View
5 tests/Doctrine/Tests/Common/DataFixtures/LoaderTest.php
@@ -35,11 +35,12 @@ public function testLoader()
$loader = new Loader();
$loader->addFixture($this->getMock('Doctrine\Common\DataFixtures\FixtureInterface'));
$loader->addFixture($this->getMock('Doctrine\Common\DataFixtures\FixtureInterface'));
+ $loader->addFixture($this->getMock('Doctrine\Common\DataFixtures\SharedFixtureInterface'));
- $this->assertEquals(2, count($loader->getFixtures()));
+ $this->assertEquals(3, count($loader->getFixtures()));
$loader->loadFromDirectory(__DIR__.'/TestFixtures');
- $this->assertEquals(4, count($loader->getFixtures()));
+ $this->assertEquals(7, count($loader->getFixtures()));
$this->assertTrue($loader->isTransient('TestFixtures\NotAFixture'));
$this->assertFalse($loader->isTransient('TestFixtures\MyFixture1'));
}
View
80 tests/Doctrine/Tests/Common/DataFixtures/ReferenceRepositoryTest.php
@@ -0,0 +1,80 @@
+<?php
+/*
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.doctrine-project.org>.
+ */
+
+namespace Doctrine\Tests\Common\DataFixtures;
+
+use Doctrine\Common\DataFixtures\ReferenceRepository;
+
+require_once __DIR__.'/TestInit.php';
+
+/**
+ * Test ReferenceRepository.
+ *
+ * @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
+ */
+class ReferenceRepositoryTest extends BaseTest
+{
+ const TEST_ENTITY_ROLE = 'Doctrine\Tests\Common\DataFixtures\TestEntity\Role';
+
+ public function testInvalidReferenceObject()
+ {
+ $em = $this->getMockEntityManager();
+ $referenceRepo = new ReferenceRepository($em);
+ $this->setExpectedException('LogicException');
+ $referenceRepo->addReference('test', new \stdClass());
+ }
+
+ public function testInvalidReferenceObjectNoPk()
+ {
+ $em = $this->getMockAnnotationReaderEntityManager();
+ $role = new TestEntity\Role;
+ $meta = $em->getClassMetadata(self::TEST_ENTITY_ROLE);
+
+ $referenceRepo = new ReferenceRepository($em);
+ $this->setExpectedException('LogicException');
+ $referenceRepo->addReference('test', $role);
+ }
+
+ public function testReferenceEntry()
+ {
+ $em = $this->getMockAnnotationReaderEntityManager();
+ $role = new TestEntity\Role;
+ $role->setName('admin');
+ $meta = $em->getClassMetadata(self::TEST_ENTITY_ROLE);
+ $meta->getReflectionProperty('id')->setValue($role, 1);
+
+ $referenceRepo = new ReferenceRepository($em);
+ $referenceRepo->addReference('test', $role);
+
+ $references = $referenceRepo->getReferences();
+ $this->assertEquals(1, count($references));
+ $this->assertArrayHasKey('test', $references);
+ $this->assertEquals(self::TEST_ENTITY_ROLE, $references['test']['class']);
+ $this->assertEquals(1, count($references['test']['identifier']));
+ $this->assertArrayHasKey('id', $references['test']['identifier']);
+ $this->assertEquals(1, $references['test']['identifier']['id']);
+ }
+
+ private function getMockReferenceRepository()
+ {
+ return $this->getMockBuilder('Doctrine\Common\DataFixtures\ReferenceRepository')
+ ->setConstructorArgs(array($this->em))
+ ->getMock();
+ }
+}
View
36 tests/Doctrine/Tests/Common/DataFixtures/TestEntity/Role.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Doctrine\Tests\Common\DataFixtures\TestEntity;
+
+/**
+ * @Entity
+ */
+class Role
+{
+ /**
+ * @Column(type="integer")
+ * @Id
+ * @GeneratedValue(strategy="IDENTITY")
+ */
+ private $id;
+
+ /**
+ * @Column(length=50, unique=true)
+ */
+ private $name;
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function setName($name)
+ {
+ $this->name = $name;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+}
View
76 tests/Doctrine/Tests/Common/DataFixtures/TestEntity/User.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Doctrine\Tests\Common\DataFixtures\TestEntity;
+
+/**
+ * @Entity
+ */
+class User
+{
+ /**
+ * @Column(type="integer")
+ * @Id
+ */
+ private $id;
+
+ /**
+ * @Column(length=32)
+ * @Id
+ */
+ private $code;
+
+ /**
+ * @Column(length=32)
+ */
+ private $password;
+
+ /**
+ * @Column(length=255, unique=true)
+ */
+ private $email;
+
+ /**
+ * @ManyToOne(targetEntity="Role")
+ */
+ private $role;
+
+ public function setId($id)
+ {
+ $this->id = $id;
+ }
+
+ public function setCode($code)
+ {
+ $this->code = $code;
+ }
+
+ public function setPassword($password)
+ {
+ $this->password = md5($password);
+ }
+
+ public function getPassword()
+ {
+ return $this->password;
+ }
+
+ public function setEmail($email)
+ {
+ $this->email = $email;
+ }
+
+ public function getEmail()
+ {
+ return $this->email;
+ }
+
+ public function setRole(Role $role)
+ {
+ $this->role = $role;
+ }
+
+ public function getRole()
+ {
+ return $this->role;
+ }
+}
View
32 tests/Doctrine/Tests/Common/DataFixtures/TestFixtures/RoleFixture.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Doctrine\Tests\Common\DataFixtures\TestFixtures;
+
+use Doctrine\Common\DataFixtures\SharedFixtureInterface;
+use Doctrine\Common\DataFixtures\ReferenceRepository;
+use Doctrine\Tests\Common\DataFixtures\TestEntity\Role;
+
+class RoleFixture implements SharedFixtureInterface
+{
+ private $referenceRepository;
+
+ public function setReferenceRepository(ReferenceRepository $referenceRepository)
+ {
+ $this->referenceRepository = $referenceRepository;
+ }
+
+ public function load($manager)
+ {
+ $adminRole = new Role();
+ $adminRole->setName('admin');
+
+ $anonymousRole = new Role;
+ $anonymousRole->setName('anonymous');
+
+ $manager->persist($adminRole);
+ $manager->persist($anonymousRole);
+ $manager->flush();
+
+ $this->referenceRepository->addReference('admin-role', $adminRole);
+ }
+}
View
24 tests/Doctrine/Tests/Common/DataFixtures/TestFixtures/UserFixture.php
@@ -0,0 +1,24 @@
+<?php
+namespace Doctrine\Tests\Common\DataFixtures\TestFixtures;
+
+use Doctrine\Common\DataFixtures\AbstractFixture;
+use Doctrine\Tests\Common\DataFixtures\TestEntity\User;
+
+class UserFixture extends AbstractFixture
+{
+ public function load($manager)
+ {
+ $admin = new User;
+ $admin->setId(4);
+ $admin->setCode('007');
+ $admin->setEmail('admin@example.com');
+ $admin->setPassword('secret');
+ $role = $this->getReference('admin-role');
+ $admin->setRole($role);
+
+ $manager->persist($admin);
+ $manager->flush();
+
+ $this->addReference('admin', $admin);
+ }
+}
View
8 tests/phpunit.dist.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit>
+ <testsuites>
+ <testsuite name="Data Fixture tests">
+ <directory suffix="Test.php">Doctrine/Tests/Common/DataFixtures/</directory>
+ </testsuite>
+ </testsuites>
+</phpunit>

0 comments on commit 669fb86

Please sign in to comment.