Failed Conditions
Push — master ( 57a950...9005c5 )
by Marco
23:43 queued 08:30
created

ProxyFactoryTest   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 191
Duplicated Lines 35.6 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 10
lcom 1
cbo 11
dl 68
loc 191
rs 10
c 1
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 9 1
A testReferenceProxyDelegatesLoadingToThePersister() 0 18 1
A testSkipMappedSuperClassesOnGeneration() 11 11 1
A testSkipEmbeddableClassesOnGeneration() 11 11 1
A testSkipAbstractClassesOnGeneration() 0 10 1
A testFailedProxyLoadingDoesNotMarkTheProxyAsInitialized() 23 23 2
A testFailedProxyCloningDoesNotMarkTheProxyAsInitialized() 23 23 2
B testProxyClonesParentFields() 0 41 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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\CompanyEmployee;
16
use Doctrine\Tests\Models\Company\CompanyPerson;
17
use Doctrine\Tests\Models\ECommerce\ECommerceFeature;
18
use Doctrine\Tests\OrmTestCase;
19
20
/**
21
 * Test the proxy generator. Its work is generating on-the-fly subclasses of a given model, which implement the Proxy pattern.
22
 * @author Giorgio Sironi <[email protected]>
23
 */
24
class ProxyFactoryTest extends OrmTestCase
25
{
26
    /**
27
     * @var ConnectionMock
28
     */
29
    private $connectionMock;
30
31
    /**
32
     * @var UnitOfWorkMock
33
     */
34
    private $uowMock;
35
36
    /**
37
     * @var EntityManagerMock
38
     */
39
    private $emMock;
40
41
    /**
42
     * @var \Doctrine\ORM\Proxy\ProxyFactory
43
     */
44
    private $proxyFactory;
45
46
    /**
47
     * {@inheritDoc}
48
     */
49
    protected function setUp()
50
    {
51
        parent::setUp();
52
        $this->connectionMock = new ConnectionMock([], new DriverMock());
53
        $this->emMock = EntityManagerMock::create($this->connectionMock);
54
        $this->uowMock = new UnitOfWorkMock($this->emMock);
55
        $this->emMock->setUnitOfWork($this->uowMock);
56
        $this->proxyFactory = new ProxyFactory($this->emMock, sys_get_temp_dir(), 'Proxies', AbstractProxyFactory::AUTOGENERATE_ALWAYS);
57
    }
58
59
    public function testReferenceProxyDelegatesLoadingToThePersister()
60
    {
61
        $identifier = ['id' => 42];
62
        $proxyClass = 'Proxies\__CG__\Doctrine\Tests\Models\ECommerce\ECommerceFeature';
63
        $persister  = $this->getMockBuilder(BasicEntityPersister::class)->setMethods(['load'])->disableOriginalConstructor()->getMock();
64
65
        $this->uowMock->setEntityPersister(ECommerceFeature::class, $persister);
66
67
        $proxy = $this->proxyFactory->getProxy(ECommerceFeature::class, $identifier);
68
69
        $persister
70
            ->expects($this->atLeastOnce())
71
            ->method('load')
72
            ->with($this->equalTo($identifier), $this->isInstanceOf($proxyClass))
73
            ->will($this->returnValue(new \stdClass()));
74
75
        $proxy->getDescription();
0 ignored issues
show
Bug introduced by
The method getDescription() does not seem to exist on object<Doctrine\Common\Proxy\Proxy>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
76
    }
77
78 View Code Duplication
    public function testSkipMappedSuperClassesOnGeneration(): void
79
    {
80
        $cm = new ClassMetadata(\stdClass::class);
81
        $cm->isMappedSuperclass = true;
82
83
        self::assertSame(
84
            0,
85
            $this->proxyFactory->generateProxyClasses([$cm]),
86
            'No proxies generated.'
87
        );
88
    }
89
90
    /**
91
     * @group 6625
92
     */
93 View Code Duplication
    public function testSkipEmbeddableClassesOnGeneration(): void
94
    {
95
        $cm = new ClassMetadata(\stdClass::class);
96
        $cm->isEmbeddedClass = true;
97
98
        self::assertSame(
99
            0,
100
            $this->proxyFactory->generateProxyClasses([$cm]),
101
            'No proxies generated.'
102
        );
103
    }
104
105
    /**
106
     * @group DDC-1771
107
     */
108
    public function testSkipAbstractClassesOnGeneration()
109
    {
110
        $cm = new ClassMetadata(AbstractClass::class);
111
        $cm->initializeReflection(new RuntimeReflectionService());
112
        $this->assertNotNull($cm->reflClass);
113
114
        $num = $this->proxyFactory->generateProxyClasses([$cm]);
115
116
        $this->assertEquals(0, $num, "No proxies generated.");
117
    }
118
119
    /**
120
     * @group DDC-2432
121
     */
122 View Code Duplication
    public function testFailedProxyLoadingDoesNotMarkTheProxyAsInitialized()
123
    {
124
        $persister = $this->getMockBuilder(BasicEntityPersister::class)->setMethods(['load'])->disableOriginalConstructor()->getMock();
125
        $this->uowMock->setEntityPersister(ECommerceFeature::class, $persister);
126
127
        /* @var $proxy \Doctrine\Common\Proxy\Proxy */
128
        $proxy = $this->proxyFactory->getProxy(ECommerceFeature::class, ['id' => 42]);
129
130
        $persister
131
            ->expects($this->atLeastOnce())
132
            ->method('load')
133
            ->will($this->returnValue(null));
134
135
        try {
136
            $proxy->getDescription();
0 ignored issues
show
Bug introduced by
The method getDescription() does not seem to exist on object<Doctrine\Common\Proxy\Proxy>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
137
            $this->fail('An exception was expected to be raised');
138
        } catch (EntityNotFoundException $exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
139
        }
140
141
        $this->assertFalse($proxy->__isInitialized());
142
        $this->assertInstanceOf('Closure', $proxy->__getInitializer(), 'The initializer wasn\'t removed');
143
        $this->assertInstanceOf('Closure', $proxy->__getCloner(), 'The cloner wasn\'t removed');
144
    }
145
146
    /**
147
     * @group DDC-2432
148
     */
149 View Code Duplication
    public function testFailedProxyCloningDoesNotMarkTheProxyAsInitialized()
150
    {
151
        $persister = $this->getMockBuilder(BasicEntityPersister::class)->setMethods(['load'])->disableOriginalConstructor()->getMock();
152
        $this->uowMock->setEntityPersister(ECommerceFeature::class, $persister);
153
154
        /* @var $proxy \Doctrine\Common\Proxy\Proxy */
155
        $proxy = $this->proxyFactory->getProxy(ECommerceFeature::class, ['id' => 42]);
156
157
        $persister
158
            ->expects($this->atLeastOnce())
159
            ->method('load')
160
            ->will($this->returnValue(null));
161
162
        try {
163
            $cloned = clone $proxy;
0 ignored issues
show
Unused Code introduced by
$cloned is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
164
            $this->fail('An exception was expected to be raised');
165
        } catch (EntityNotFoundException $exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
166
        }
167
168
        $this->assertFalse($proxy->__isInitialized());
169
        $this->assertInstanceOf('Closure', $proxy->__getInitializer(), 'The initializer wasn\'t removed');
170
        $this->assertInstanceOf('Closure', $proxy->__getCloner(), 'The cloner wasn\'t removed');
171
    }
172
173
    public function testProxyClonesParentFields()
174
    {
175
        $companyEmployee = new CompanyEmployee();
176
        $companyEmployee->setSalary(1000); // A property on the CompanyEmployee
177
        $companyEmployee->setName('Bob'); // A property on the parent class, CompanyPerson
178
179
        // Set the id of the CompanyEmployee (which is in the parent CompanyPerson)
180
        $property = new \ReflectionProperty(CompanyPerson::class, 'id');
181
182
        $property->setAccessible(true);
183
        $property->setValue($companyEmployee, 42);
184
185
        $classMetaData = $this->emMock->getClassMetadata(CompanyEmployee::class);
186
187
        $persister = $this
188
            ->getMockBuilder(BasicEntityPersister::class)
189
            ->setMethods(['load', 'getClassMetadata'])
190
            ->disableOriginalConstructor()
191
            ->getMock();
192
        $this->uowMock->setEntityPersister(CompanyEmployee::class, $persister);
193
194
        /* @var $proxy \Doctrine\Common\Proxy\Proxy */
195
        $proxy = $this->proxyFactory->getProxy(CompanyEmployee::class, ['id' => 42]);
196
197
        $persister
198
            ->expects(self::atLeastOnce())
199
            ->method('load')
200
            ->willReturn($companyEmployee);
201
202
        $persister
203
            ->expects(self::atLeastOnce())
204
            ->method('getClassMetadata')
205
            ->willReturn($classMetaData);
206
207
        /* @var $cloned CompanyEmployee */
208
        $cloned = clone $proxy;
209
210
        self::assertSame(42, $cloned->getId(), 'Expected the Id to be cloned');
211
        self::assertSame(1000, $cloned->getSalary(), 'Expect properties on the CompanyEmployee class to be cloned');
212
        self::assertSame('Bob', $cloned->getName(), 'Expect properties on the CompanyPerson class to be cloned');
213
    }
214
}
215
216
abstract class AbstractClass
217
{
218
219
}
220