3 namespace Doctrine\Tests\ORM\Proxy;
5 use Doctrine\ORM\Proxy\ProxyFactory;
6 use Doctrine\Tests\Mocks\ConnectionMock;
7 use Doctrine\Tests\Mocks\EntityManagerMock;
8 use Doctrine\Tests\Mocks\UnitOfWorkMock;
9 use Doctrine\Tests\Models\ECommerce\ECommerceCart;
10 use Doctrine\Tests\Models\ECommerce\ECommerceCustomer;
11 use Doctrine\Tests\Models\ECommerce\ECommerceFeature;
12 use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
13 use Doctrine\Tests\Models\ECommerce\ECommerceShipping;
15 require_once __DIR__ . '/../../TestInit.php';
18 * Test the proxy generator. Its work is generating on-the-fly subclasses of a given model, which implement the Proxy pattern.
19 * @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
21 class ProxyClassGeneratorTest extends \Doctrine\Tests\OrmTestCase
23 private $_connectionMock;
28 * @var \Doctrine\ORM\Proxy\ProxyFactory
30 private $_proxyFactory;
32 protected function setUp()
35 $this->_connectionMock = new ConnectionMock(array(), new \Doctrine\Tests\Mocks\DriverMock());
36 $this->_emMock = EntityManagerMock::create($this->_connectionMock);
37 $this->_uowMock = new UnitOfWorkMock($this->_emMock);
38 $this->_emMock->setUnitOfWork($this->_uowMock);
40 $this->_proxyFactory = new ProxyFactory($this->_emMock, __DIR__ . '/generated', 'Proxies', true);
43 protected function tearDown()
45 foreach (new \DirectoryIterator(__DIR__ . '/generated') as $file) {
46 if (strstr($file->getFilename(), '.php')) {
47 unlink($file->getPathname());
52 public function testReferenceProxyDelegatesLoadingToThePersister()
54 $identifier = array('id' => 42);
55 $proxyClass = 'Proxies\__CG__\Doctrine\Tests\Models\ECommerce\ECommerceFeature';
56 $persister = $this->_getMockPersister();
57 $this->_uowMock->setEntityPersister('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $persister);
59 $proxy = $this->_proxyFactory->getProxy('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $identifier);
61 $persister->expects($this->atLeastOnce())
63 ->with($this->equalTo($identifier), $this->isInstanceOf($proxyClass))
64 ->will($this->returnValue(new \stdClass())); // fake return of entity instance
66 $proxy->getDescription();
69 public function testReferenceProxyExecutesLoadingOnlyOnce()
71 $identifier = array('id' => 42);
72 $proxyClass = 'Proxies\__CG__\Doctrine\Tests\Models\ECommerce\ECommerceFeature';
73 $persister = $this->_getMockPersister();
74 $this->_uowMock->setEntityPersister('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $persister);
75 $proxy = $this->_proxyFactory->getProxy('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $identifier);
77 $persister->expects($this->atLeastOnce())
79 ->with($this->equalTo($identifier), $this->isInstanceOf($proxyClass))
80 ->will($this->returnValue(new \stdClass())); // fake return of entity instance
81 $proxy->getDescription();
85 public function testReferenceProxyRespectsMethodsParametersTypeHinting()
87 $proxyClass = 'Proxies\DoctrineTestsModelsECommerceECommerceFeatureProxy';
88 $persister = $this->_getMockPersister();
89 $this->_uowMock->setEntityPersister('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $persister);
90 $proxy = $this->_proxyFactory->getProxy('Doctrine\Tests\Models\ECommerce\ECommerceFeature', null);
92 $method = new \ReflectionMethod(get_class($proxy), 'setProduct');
93 $params = $method->getParameters();
95 $this->assertEquals(1, count($params));
96 $this->assertEquals('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $params[0]->getClass()->getName());
100 * Test that the proxy behaves in regard to methods like &foo() correctly
102 public function testProxyRespectsMethodsWhichReturnValuesByReference() {
103 $proxy = $this->_proxyFactory->getProxy('Doctrine\Tests\Models\Forum\ForumEntry', null);
104 $method = new \ReflectionMethod(get_class($proxy), 'getTopicByReference');
106 $this->assertTrue($method->returnsReference());
109 public function testCreatesAssociationProxyAsSubclassOfTheOriginalOne()
111 $proxyClass = 'Proxies\__CG__\Doctrine\Tests\Models\ECommerce\ECommerceFeature';
112 $this->assertTrue(is_subclass_of($proxyClass, 'Doctrine\Tests\Models\ECommerce\ECommerceFeature'));
116 public function testAllowsConcurrentCreationOfBothProxyTypes()
118 $referenceProxyClass = 'Proxies\DoctrineTestsModelsECommerceECommerceFeatureProxy';
119 $associationProxyClass = 'Proxies\DoctrineTestsModelsECommerceECommerceFeatureAProxy';
120 $this->assertNotEquals($referenceProxyClass, $associationProxyClass);
123 public function testNonNamespacedProxyGeneration()
125 require_once dirname(__FILE__)."/fixtures/NonNamespacedProxies.php";
127 $className = "\DoctrineOrmTestEntity";
128 $proxyName = "DoctrineOrmTestEntity";
129 $classMetadata = new \Doctrine\ORM\Mapping\ClassMetadata($className);
130 $classMetadata->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
131 $classMetadata->mapField(array('fieldName' => 'id', 'type' => 'integer'));
132 $classMetadata->setIdentifier(array('id'));
134 $this->_proxyFactory->generateProxyClasses(array($classMetadata));
136 $classCode = file_get_contents(dirname(__FILE__)."/generated/__CG__".$proxyName.".php");
138 $this->assertNotContains("class DoctrineOrmTestEntity extends \\\\DoctrineOrmTestEntity", $classCode);
139 $this->assertContains("class DoctrineOrmTestEntity extends \\DoctrineOrmTestEntity", $classCode);
142 public function testClassWithSleepProxyGeneration()
144 $className = "\Doctrine\Tests\ORM\Proxy\SleepClass";
145 $proxyName = "DoctrineTestsORMProxySleepClass";
146 $classMetadata = new \Doctrine\ORM\Mapping\ClassMetadata($className);
147 $classMetadata->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
148 $classMetadata->mapField(array('fieldName' => 'id', 'type' => 'integer'));
149 $classMetadata->setIdentifier(array('id'));
151 $this->_proxyFactory->generateProxyClasses(array($classMetadata));
153 $classCode = file_get_contents(dirname(__FILE__)."/generated/__CG__".$proxyName.".php");
155 $this->assertEquals(1, substr_count($classCode, 'function __sleep'));
161 public function testSkipAbstractClassesOnGeneration()
163 $cm = new \Doctrine\ORM\Mapping\ClassMetadata(__NAMESPACE__ . '\\AbstractClass');
164 $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
165 $this->assertNotNull($cm->reflClass);
167 $num = $this->_proxyFactory->generateProxyClasses(array($cm));
169 $this->assertEquals(0, $num, "No proxies generated.");
172 public function testNoConfigDir_ThrowsException()
174 $this->setExpectedException('Doctrine\ORM\Proxy\ProxyException');
175 new ProxyFactory($this->_getTestEntityManager(), null, null);
178 public function testNoNamespace_ThrowsException()
180 $this->setExpectedException('Doctrine\ORM\Proxy\ProxyException');
181 new ProxyFactory($this->_getTestEntityManager(), __DIR__ . '/generated', null);
184 protected function _getMockPersister()
186 $persister = $this->getMock('Doctrine\ORM\Persisters\BasicEntityPersister', array('load'), array(), '', false);
195 public function __sleep()
201 abstract class AbstractClass