Completed
Push — master ( 221050...cd1172 )
by Marco
10:08
created

ProxyFactoryTest::testProxyClonesParentFields()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 41
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 41
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 27
nc 1
nop 0
1
<?php
2
3
namespace Doctrine\Tests\ORM\Proxy;
4
5
use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService;
6
use Doctrine\Common\Proxy\AbstractProxyFactory;
7
use Doctrine\ORM\EntityNotFoundException;
8
use Doctrine\ORM\Mapping\ClassMetadata;
9
use Doctrine\ORM\Persisters\Entity\BasicEntityPersister;
10
use Doctrine\ORM\Proxy\ProxyFactory;
11
use Doctrine\Tests\Mocks\ConnectionMock;
12
use Doctrine\Tests\Mocks\DriverMock;
13
use Doctrine\Tests\Mocks\EntityManagerMock;
14
use Doctrine\Tests\Mocks\UnitOfWorkMock;
15
use Doctrine\Tests\Models\Company\CompanyPerson;
16
use Doctrine\Tests\OrmTestCase;
17
use Doctrine\Tests\Models\Company\CompanyEmployee;
18
19
/**
20
 * Test the proxy generator. Its work is generating on-the-fly subclasses of a given model, which implement the Proxy pattern.
21
 * @author Giorgio Sironi <[email protected]>
22
 */
23
class ProxyFactoryTest extends OrmTestCase
24
{
25
    /**
26
     * @var ConnectionMock
27
     */
28
    private $connectionMock;
29
30
    /**
31
     * @var UnitOfWorkMock
32
     */
33
    private $uowMock;
34
35
    /**
36
     * @var EntityManagerMock
37
     */
38
    private $emMock;
39
40
    /**
41
     * @var \Doctrine\ORM\Proxy\ProxyFactory
42
     */
43
    private $proxyFactory;
44
45
    /**
46
     * {@inheritDoc}
47
     */
48
    protected function setUp()
49
    {
50
        parent::setUp();
51
        $this->connectionMock = new ConnectionMock(array(), new DriverMock());
52
        $this->emMock = EntityManagerMock::create($this->connectionMock);
53
        $this->uowMock = new UnitOfWorkMock($this->emMock);
54
        $this->emMock->setUnitOfWork($this->uowMock);
55
        $this->proxyFactory = new ProxyFactory($this->emMock, sys_get_temp_dir(), 'Proxies', AbstractProxyFactory::AUTOGENERATE_ALWAYS);
56
    }
57
58
    public function testReferenceProxyDelegatesLoadingToThePersister()
59
    {
60
        $identifier = array('id' => 42);
61
        $proxyClass = 'Proxies\__CG__\Doctrine\Tests\Models\ECommerce\ECommerceFeature';
62
        $persister  = $this->getMockBuilder(BasicEntityPersister::class)->setMethods(array('load'))->disableOriginalConstructor()->getMock();
63
64
        $this->uowMock->setEntityPersister('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $persister);
65
66
        $proxy = $this->proxyFactory->getProxy('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $identifier);
67
68
        $persister
69
            ->expects($this->atLeastOnce())
70
            ->method('load')
71
            ->with($this->equalTo($identifier), $this->isInstanceOf($proxyClass))
72
            ->will($this->returnValue(new \stdClass()));
73
74
        $proxy->getDescription();
75
    }
76
77
    /**
78
     * @group DDC-1771
79
     */
80
    public function testSkipAbstractClassesOnGeneration()
81
    {
82
        $cm = new ClassMetadata(__NAMESPACE__ . '\\AbstractClass');
83
        $cm->initializeReflection(new RuntimeReflectionService());
84
        $this->assertNotNull($cm->reflClass);
85
86
        $num = $this->proxyFactory->generateProxyClasses(array($cm));
87
88
        $this->assertEquals(0, $num, "No proxies generated.");
89
    }
90
91
    /**
92
     * @group DDC-2432
93
     */
94
    public function testFailedProxyLoadingDoesNotMarkTheProxyAsInitialized()
95
    {
96
        $persister = $this->getMockBuilder(BasicEntityPersister::class)->setMethods(array('load'))->disableOriginalConstructor()->getMock();
97
        $this->uowMock->setEntityPersister('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $persister);
98
99
        /* @var $proxy \Doctrine\Common\Proxy\Proxy */
100
        $proxy = $this->proxyFactory->getProxy('Doctrine\Tests\Models\ECommerce\ECommerceFeature', array('id' => 42));
101
102
        $persister
103
            ->expects($this->atLeastOnce())
104
            ->method('load')
105
            ->will($this->returnValue(null));
106
107
        try {
108
            $proxy->getDescription();
109
            $this->fail('An exception was expected to be raised');
110
        } catch (EntityNotFoundException $exception) {
111
        }
112
113
        $this->assertFalse($proxy->__isInitialized());
114
        $this->assertInstanceOf('Closure', $proxy->__getInitializer(), 'The initializer wasn\'t removed');
115
        $this->assertInstanceOf('Closure', $proxy->__getCloner(), 'The cloner wasn\'t removed');
116
    }
117
118
    /**
119
     * @group DDC-2432
120
     */
121
    public function testFailedProxyCloningDoesNotMarkTheProxyAsInitialized()
122
    {
123
        $persister = $this->getMockBuilder(BasicEntityPersister::class)->setMethods(array('load'))->disableOriginalConstructor()->getMock();
124
        $this->uowMock->setEntityPersister('Doctrine\Tests\Models\ECommerce\ECommerceFeature', $persister);
125
126
        /* @var $proxy \Doctrine\Common\Proxy\Proxy */
127
        $proxy = $this->proxyFactory->getProxy('Doctrine\Tests\Models\ECommerce\ECommerceFeature', array('id' => 42));
128
129
        $persister
130
            ->expects($this->atLeastOnce())
131
            ->method('load')
132
            ->will($this->returnValue(null));
133
134
        try {
135
            $cloned = clone $proxy;
136
            $this->fail('An exception was expected to be raised');
137
        } catch (EntityNotFoundException $exception) {
138
        }
139
140
        $this->assertFalse($proxy->__isInitialized());
141
        $this->assertInstanceOf('Closure', $proxy->__getInitializer(), 'The initializer wasn\'t removed');
142
        $this->assertInstanceOf('Closure', $proxy->__getCloner(), 'The cloner wasn\'t removed');
143
    }
144
145
    public function testProxyClonesParentFields()
146
    {
147
        $companyEmployee = new CompanyEmployee();
148
        $companyEmployee->setSalary(1000); // A property on the CompanyEmployee
149
        $companyEmployee->setName('Bob'); // A property on the parent class, CompanyPerson
150
151
        // Set the id of the CompanyEmployee (which is in the parent CompanyPerson)
152
        $property = new \ReflectionProperty(CompanyPerson::class, 'id');
153
154
        $property->setAccessible(true);
155
        $property->setValue($companyEmployee, 42);
156
157
        $classMetaData = $this->emMock->getClassMetadata(CompanyEmployee::class);
158
159
        $persister = $this
160
            ->getMockBuilder(BasicEntityPersister::class)
161
            ->setMethods(['load', 'getClassMetadata'])
162
            ->disableOriginalConstructor()
163
            ->getMock();
164
        $this->uowMock->setEntityPersister(CompanyEmployee::class, $persister);
165
166
        /* @var $proxy \Doctrine\Common\Proxy\Proxy */
167
        $proxy = $this->proxyFactory->getProxy(CompanyEmployee::class, ['id' => 42]);
168
169
        $persister
170
            ->expects(self::atLeastOnce())
171
            ->method('load')
172
            ->willReturn($companyEmployee);
173
174
        $persister
175
            ->expects(self::atLeastOnce())
176
            ->method('getClassMetadata')
177
            ->willReturn($classMetaData);
178
179
        /* @var $cloned CompanyEmployee */
180
        $cloned = clone $proxy;
181
182
        self::assertSame(42, $cloned->getId(), 'Expected the Id to be cloned');
183
        self::assertSame(1000, $cloned->getSalary(), 'Expect properties on the CompanyEmployee class to be cloned');
184
        self::assertSame('Bob', $cloned->getName(), 'Expect properties on the CompanyPerson class to be cloned');
185
    }
186
}
187
188
abstract class AbstractClass
189
{
190
191
}
192