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 |
||
26 | final class GenericServiceInvokeControllerTest extends TestCase |
||
27 | { |
||
28 | |||
29 | /** |
||
30 | * @var ControllerHelperInterface |
||
31 | */ |
||
32 | private $controllerHelper; |
||
33 | |||
34 | /** |
||
35 | * @var ArgumentCompilerInterface |
||
36 | */ |
||
37 | private $argumentCompiler; |
||
38 | |||
39 | /** |
||
40 | * @var ContainerInterface |
||
41 | */ |
||
42 | private $container; |
||
43 | |||
44 | public function setUp() |
||
50 | |||
51 | /** |
||
52 | * @test |
||
53 | */ |
||
54 | View Code Duplication | public function shouldPreventConstructorCalledAgain() |
|
55 | { |
||
56 | $this->expectException(InvalidArgumentException::class); |
||
57 | |||
58 | $controller = new GenericServiceInvokeController( |
||
59 | $this->controllerHelper, |
||
60 | $this->argumentCompiler, |
||
61 | $this->container, |
||
62 | [ |
||
63 | 'service' => 'some_service', |
||
64 | 'method' => 'doFoo' |
||
65 | ] |
||
66 | ); |
||
67 | |||
68 | $controller->__construct( |
||
69 | $this->controllerHelper, |
||
70 | $this->argumentCompiler, |
||
71 | $this->container, |
||
72 | [ |
||
73 | 'service' => 'some_service', |
||
74 | 'method' => 'doFoo' |
||
75 | ] |
||
76 | ); |
||
77 | } |
||
78 | |||
79 | /** |
||
80 | * @test |
||
81 | */ |
||
82 | View Code Duplication | public function shouldFailIfServiceIsMissing() |
|
95 | |||
96 | /** |
||
97 | * @test |
||
98 | */ |
||
99 | View Code Duplication | public function shouldFailIfMethodIsMissing() |
|
112 | |||
113 | /** |
||
114 | * @test |
||
115 | */ |
||
116 | View Code Duplication | public function shouldCallService() |
|
117 | { |
||
118 | /** @var Request $request */ |
||
119 | $request = $this->createMock(Request::class); |
||
120 | |||
121 | /** @var SampleService $service */ |
||
122 | $service = $this->createMock(SampleService::class); |
||
123 | |||
124 | $service->expects($this->once())->method('doFoo')->with( |
||
125 | $this->equalTo('lorem'), |
||
126 | $this->equalTo('ipsum') |
||
127 | ); |
||
128 | |||
129 | $this->container->expects($this->once())->method('get')->with( |
||
130 | $this->equalTo('some_service') |
||
131 | )->willReturn($service); |
||
132 | |||
133 | $this->argumentCompiler->expects($this->once())->method('buildCallArguments')->with( |
||
134 | $this->equalTo(new ReflectionMethod($service, 'doFoo')), |
||
135 | $this->equalTo(['lorem' => 'ipsum']), |
||
136 | $this->identicalTo($request) |
||
137 | )->willReturn(['lorem', 'ipsum']); |
||
138 | |||
139 | /** @var string $expectedResponseContent */ |
||
140 | $expectedResponseContent = "Service call completed"; |
||
141 | |||
142 | $controller = new GenericServiceInvokeController( |
||
143 | $this->controllerHelper, |
||
144 | $this->argumentCompiler, |
||
145 | $this->container, |
||
146 | [ |
||
147 | 'service' => 'some_service', |
||
148 | 'method' => 'doFoo', |
||
149 | 'arguments' => ['lorem' => 'ipsum'] |
||
150 | ] |
||
151 | ); |
||
152 | |||
153 | /** @var Response $actualResponse */ |
||
154 | $actualResponse = $controller->callService($request); |
||
155 | |||
156 | $this->assertEquals($expectedResponseContent, $actualResponse->getContent()); |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * @test |
||
161 | */ |
||
162 | View Code Duplication | public function shouldCheckIfAccessIsGranted() |
|
191 | |||
192 | /** |
||
193 | * @test |
||
194 | */ |
||
195 | public function shouldThrowExceptionIfServiceNotFound() |
||
219 | |||
220 | /** |
||
221 | * @test |
||
222 | */ |
||
223 | View Code Duplication | public function shouldBeCallableByInvokingController() |
|
267 | |||
268 | /** |
||
269 | * @test |
||
270 | */ |
||
271 | View Code Duplication | public function shouldRejectCallWithoutRequest() |
|
289 | |||
290 | } |
||
291 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..