ProxyClassGeneratorTest.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <?php
  2. namespace Doctrine\Tests\ORM\Proxy;
  3. use Doctrine\ORM\Proxy\ProxyFactory;
  4. use Doctrine\Tests\Mocks\ConnectionMock;
  5. use Doctrine\Tests\Mocks\EntityManagerMock;
  6. use Doctrine\Tests\Mocks\UnitOfWorkMock;
  7. use Doctrine\Tests\Models\ECommerce\ECommerceCart;
  8. use Doctrine\Tests\Models\ECommerce\ECommerceCustomer;
  9. use Doctrine\Tests\Models\ECommerce\ECommerceFeature;
  10. use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
  11. use Doctrine\Tests\Models\ECommerce\ECommerceShipping;
  12. require_once __DIR__ . '/../../TestInit.php';
  13. /**
  14. * Test the proxy generator. Its work is generating on-the-fly subclasses of a given model, which implement the Proxy pattern.
  15. * @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
  16. */
  17. class ProxyClassGeneratorTest extends \Doctrine\Tests\OrmTestCase
  18. {
  19. private $_connectionMock;
  20. private $_uowMock;
  21. private $_emMock;
  22. /**
  23. * @var \Doctrine\ORM\Proxy\ProxyFactory
  24. */
  25. private $_proxyFactory;
  26. protected function setUp()
  27. {
  28. parent::setUp();
  29. $this->_connectionMock = new ConnectionMock(array(), new \Doctrine\Tests\Mocks\DriverMock());
  30. $this->_emMock = EntityManagerMock::create($this->_connectionMock);
  31. $this->_uowMock = new UnitOfWorkMock($this->_emMock);
  32. $this->_emMock->setUnitOfWork($this->_uowMock);
  33. // SUT
  34. $this->_proxyFactory = new ProxyFactory($this->_emMock, __DIR__ . '/generated', 'Proxies', true);
  35. }
  36. protected function tearDown()
  37. {
  38. foreach (new \DirectoryIterator(__DIR__ . '/generated') as $file) {
  39. if (strstr($file->getFilename(), '.php')) {
  40. unlink($file->getPathname());
  41. }
  42. }
  43. }
  44. public function testReferenceProxyDelegatesLoadingToThePersister()
  45. {
  46. $identifier = array('id' => 42);
  47. $proxyClass = 'Proxies\__CG__\Doctrine\Tests\Models\ECommerce\ECommerceFeature';
  48. $persister = $this->_getMockPersister();
  49. $this->_uowMock->setEntityPersister('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $persister);
  50. $proxy = $this->_proxyFactory->getProxy('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $identifier);
  51. $persister->expects($this->atLeastOnce())
  52. ->method('load')
  53. ->with($this->equalTo($identifier), $this->isInstanceOf($proxyClass))
  54. ->will($this->returnValue(new \stdClass())); // fake return of entity instance
  55. $proxy->getDescription();
  56. }
  57. public function testReferenceProxyExecutesLoadingOnlyOnce()
  58. {
  59. $identifier = array('id' => 42);
  60. $proxyClass = 'Proxies\__CG__\Doctrine\Tests\Models\ECommerce\ECommerceFeature';
  61. $persister = $this->_getMockPersister();
  62. $this->_uowMock->setEntityPersister('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $persister);
  63. $proxy = $this->_proxyFactory->getProxy('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $identifier);
  64. $persister->expects($this->atLeastOnce())
  65. ->method('load')
  66. ->with($this->equalTo($identifier), $this->isInstanceOf($proxyClass))
  67. ->will($this->returnValue(new \stdClass())); // fake return of entity instance
  68. $proxy->getDescription();
  69. $proxy->getProduct();
  70. }
  71. public function testReferenceProxyRespectsMethodsParametersTypeHinting()
  72. {
  73. $proxyClass = 'Proxies\DoctrineTestsModelsECommerceECommerceFeatureProxy';
  74. $persister = $this->_getMockPersister();
  75. $this->_uowMock->setEntityPersister('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $persister);
  76. $proxy = $this->_proxyFactory->getProxy('Doctrine\Tests\Models\ECommerce\ECommerceFeature', null);
  77. $method = new \ReflectionMethod(get_class($proxy), 'setProduct');
  78. $params = $method->getParameters();
  79. $this->assertEquals(1, count($params));
  80. $this->assertEquals('Doctrine\Tests\Models\ECommerce\ECommerceProduct', $params[0]->getClass()->getName());
  81. }
  82. /**
  83. * Test that the proxy behaves in regard to methods like &foo() correctly
  84. */
  85. public function testProxyRespectsMethodsWhichReturnValuesByReference() {
  86. $proxy = $this->_proxyFactory->getProxy('Doctrine\Tests\Models\Forum\ForumEntry', null);
  87. $method = new \ReflectionMethod(get_class($proxy), 'getTopicByReference');
  88. $this->assertTrue($method->returnsReference());
  89. }
  90. public function testCreatesAssociationProxyAsSubclassOfTheOriginalOne()
  91. {
  92. $proxyClass = 'Proxies\__CG__\Doctrine\Tests\Models\ECommerce\ECommerceFeature';
  93. $this->assertTrue(is_subclass_of($proxyClass, 'Doctrine\Tests\Models\ECommerce\ECommerceFeature'));
  94. }
  95. public function testAllowsConcurrentCreationOfBothProxyTypes()
  96. {
  97. $referenceProxyClass = 'Proxies\DoctrineTestsModelsECommerceECommerceFeatureProxy';
  98. $associationProxyClass = 'Proxies\DoctrineTestsModelsECommerceECommerceFeatureAProxy';
  99. $this->assertNotEquals($referenceProxyClass, $associationProxyClass);
  100. }
  101. public function testNonNamespacedProxyGeneration()
  102. {
  103. require_once dirname(__FILE__)."/fixtures/NonNamespacedProxies.php";
  104. $className = "\DoctrineOrmTestEntity";
  105. $proxyName = "DoctrineOrmTestEntity";
  106. $classMetadata = new \Doctrine\ORM\Mapping\ClassMetadata($className);
  107. $classMetadata->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
  108. $classMetadata->mapField(array('fieldName' => 'id', 'type' => 'integer'));
  109. $classMetadata->setIdentifier(array('id'));
  110. $this->_proxyFactory->generateProxyClasses(array($classMetadata));
  111. $classCode = file_get_contents(dirname(__FILE__)."/generated/__CG__".$proxyName.".php");
  112. $this->assertNotContains("class DoctrineOrmTestEntity extends \\\\DoctrineOrmTestEntity", $classCode);
  113. $this->assertContains("class DoctrineOrmTestEntity extends \\DoctrineOrmTestEntity", $classCode);
  114. }
  115. public function testClassWithSleepProxyGeneration()
  116. {
  117. $className = "\Doctrine\Tests\ORM\Proxy\SleepClass";
  118. $proxyName = "DoctrineTestsORMProxySleepClass";
  119. $classMetadata = new \Doctrine\ORM\Mapping\ClassMetadata($className);
  120. $classMetadata->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
  121. $classMetadata->mapField(array('fieldName' => 'id', 'type' => 'integer'));
  122. $classMetadata->setIdentifier(array('id'));
  123. $this->_proxyFactory->generateProxyClasses(array($classMetadata));
  124. $classCode = file_get_contents(dirname(__FILE__)."/generated/__CG__".$proxyName.".php");
  125. $this->assertEquals(1, substr_count($classCode, 'function __sleep'));
  126. }
  127. /**
  128. * @group DDC-1771
  129. */
  130. public function testSkipAbstractClassesOnGeneration()
  131. {
  132. $cm = new \Doctrine\ORM\Mapping\ClassMetadata(__NAMESPACE__ . '\\AbstractClass');
  133. $cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
  134. $this->assertNotNull($cm->reflClass);
  135. $num = $this->_proxyFactory->generateProxyClasses(array($cm));
  136. $this->assertEquals(0, $num, "No proxies generated.");
  137. }
  138. public function testNoConfigDir_ThrowsException()
  139. {
  140. $this->setExpectedException('Doctrine\ORM\Proxy\ProxyException');
  141. new ProxyFactory($this->_getTestEntityManager(), null, null);
  142. }
  143. public function testNoNamespace_ThrowsException()
  144. {
  145. $this->setExpectedException('Doctrine\ORM\Proxy\ProxyException');
  146. new ProxyFactory($this->_getTestEntityManager(), __DIR__ . '/generated', null);
  147. }
  148. protected function _getMockPersister()
  149. {
  150. $persister = $this->getMock('Doctrine\ORM\Persisters\BasicEntityPersister', array('load'), array(), '', false);
  151. return $persister;
  152. }
  153. }
  154. class SleepClass
  155. {
  156. public $id;
  157. public function __sleep()
  158. {
  159. return array('id');
  160. }
  161. }
  162. abstract class AbstractClass
  163. {
  164. }