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 |
||
16 | class TrailingSlashControllerProviderTest extends \PHPUnit_Framework_TestCase |
||
17 | { |
||
18 | public function testShouldInitalize() |
||
25 | |||
26 | public function testShouldRegisterUrlMatcher() |
||
27 | { |
||
28 | $app = new Application(); |
||
29 | |||
30 | $app->register(new TrailingSlashControllerProvider()); |
||
31 | |||
32 | $this->assertInstanceOf(UrlMatcher::class, $app['url_matcher']); |
||
33 | } |
||
34 | |||
35 | public function testShouldMount() |
||
36 | { |
||
37 | $app = new Application(); |
||
38 | |||
39 | // `mount` should return the application. |
||
40 | $this->assertSame( |
||
41 | $app, |
||
42 | $app->mount('/', new TrailingSlashControllerProvider()) |
||
43 | ); |
||
44 | } |
||
45 | |||
46 | /** |
||
47 | * @dataProvider requestMethodProvider |
||
48 | * |
||
49 | * @param string $method |
||
50 | */ |
||
51 | View Code Duplication | public function testShouldRespondOkWithoutTrailingSlash($method) |
|
|
|||
52 | { |
||
53 | $app = new Application(); |
||
54 | |||
55 | $app->match('/foo/', function () { |
||
56 | return 'hunter42'; |
||
57 | })->method($method); |
||
58 | |||
59 | $app->match('/foo/bar/', function () { |
||
60 | return 'What\'s the question?'; |
||
61 | })->method($method); |
||
62 | |||
63 | $app->match('/foo/bar/baz/', function () { |
||
64 | return 'Fizz Buzz'; |
||
65 | })->method($method); |
||
66 | |||
67 | $app->register(new TrailingSlashControllerProvider()); |
||
68 | $app->mount('/', new TrailingSlashControllerProvider()); |
||
69 | |||
70 | $request = Request::create('/foo', $method); |
||
71 | $response = $app->handle($request); |
||
72 | |||
73 | $this->assertEquals(200, $response->getStatusCode()); |
||
74 | |||
75 | $request = Request::create('/foo/bar', $method); |
||
76 | $response = $app->handle($request); |
||
77 | |||
78 | $this->assertEquals(200, $response->getStatusCode()); |
||
79 | |||
80 | $request = Request::create('/foo/bar/baz', $method); |
||
81 | $response = $app->handle($request); |
||
82 | |||
83 | $this->assertEquals(200, $response->getStatusCode()); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * This just shows that the mount order for the controller provider doesn't |
||
88 | * matter when all routes are defined with a trailing slash. |
||
89 | * |
||
90 | * @dataProvider requestMethodProvider |
||
91 | * |
||
92 | * @param string $method |
||
93 | */ |
||
94 | View Code Duplication | public function testShouldRespondOkWithoutTrailingSlashWhenMountedFirst($method) |
|
95 | { |
||
96 | $app = new Application(); |
||
97 | |||
98 | $app->register(new TrailingSlashControllerProvider()); |
||
99 | $app->mount('/', new TrailingSlashControllerProvider()); |
||
100 | |||
101 | $app->match('/foo/', function () { |
||
102 | return 'hunter42'; |
||
103 | })->method($method); |
||
104 | |||
105 | $app->match('/foo/bar/', function () { |
||
106 | return 'What\'s the question?'; |
||
107 | })->method($method); |
||
108 | |||
109 | $app->match('/foo/bar/baz/', function () { |
||
110 | return 'Fizz Buzz'; |
||
111 | })->method($method); |
||
112 | |||
113 | $request = Request::create('/foo', $method); |
||
114 | $response = $app->handle($request); |
||
115 | |||
116 | $this->assertEquals(200, $response->getStatusCode()); |
||
117 | |||
118 | $request = Request::create('/foo/bar', $method); |
||
119 | $response = $app->handle($request); |
||
120 | |||
121 | $this->assertEquals(200, $response->getStatusCode()); |
||
122 | |||
123 | $request = Request::create('/foo/bar/baz', $method); |
||
124 | $response = $app->handle($request); |
||
125 | |||
126 | $this->assertEquals(200, $response->getStatusCode()); |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * This just shows that the controller provider is compatiable with other |
||
131 | * controller providers. |
||
132 | * |
||
133 | * @dataProvider requestMethodProvider |
||
134 | * |
||
135 | * @param string $method |
||
136 | */ |
||
137 | public function testShouldRespondOkWithoutTrailingSlashWithMountedControllers($method) |
||
138 | { |
||
139 | $app = new Application(); |
||
140 | |||
141 | $app->register(new TrailingSlashControllerProvider()); |
||
142 | $app->mount('/', new TrailingSlashControllerProvider()); |
||
143 | |||
144 | $controller = $app['controllers_factory']; |
||
145 | |||
146 | $controller->match('/foo/', function () { |
||
147 | return 'hunter42'; |
||
148 | })->method($method); |
||
149 | |||
150 | $controller->match('/foo/bar/', function () { |
||
151 | return 'hunter42'; |
||
152 | })->method($method); |
||
153 | |||
154 | $controller->match('/foo/bar/baz/', function () { |
||
155 | return 'hunter42'; |
||
156 | })->method($method); |
||
157 | |||
158 | $provider = Mockery::mock(ControllerProviderInterface::class); |
||
159 | $provider->shouldReceive('connect')->andReturn($controller); |
||
160 | |||
161 | $app->mount('/', $provider); |
||
162 | |||
163 | $request = Request::create('/foo', $method); |
||
164 | $response = $app->handle($request); |
||
165 | |||
166 | $this->assertEquals(200, $response->getStatusCode()); |
||
167 | |||
168 | $request = Request::create('/foo/bar', $method); |
||
169 | $response = $app->handle($request); |
||
170 | |||
171 | $this->assertEquals(200, $response->getStatusCode()); |
||
172 | |||
173 | $request = Request::create('/foo/bar/baz', $method); |
||
174 | $response = $app->handle($request); |
||
175 | |||
176 | $this->assertEquals(200, $response->getStatusCode()); |
||
177 | } |
||
178 | |||
179 | /** |
||
180 | * @return array |
||
181 | */ |
||
182 | public function requestMethodProvider() |
||
196 | |||
197 | public function testShouldRespondOkToHeadWithoutTrailingSlash() |
||
198 | { |
||
199 | $app = new Application(); |
||
200 | |||
201 | $app->get('/foo/', function () { |
||
202 | return 'hunter42'; |
||
203 | }); |
||
204 | |||
205 | $app->get('/foo/bar/', function () { |
||
206 | return 'What\'s the question?'; |
||
207 | }); |
||
208 | |||
209 | $app->get('/foo/bar/baz/', function () { |
||
210 | return 'Fizz Buzz'; |
||
211 | }); |
||
212 | |||
213 | $app->register(new TrailingSlashControllerProvider()); |
||
214 | $app->mount('/', new TrailingSlashControllerProvider()); |
||
215 | |||
216 | $request = Request::create('/foo', 'HEAD'); |
||
217 | $response = $app->handle($request); |
||
218 | |||
219 | $this->assertEquals(200, $response->getStatusCode()); |
||
220 | |||
221 | $request = Request::create('/foo/bar', 'HEAD'); |
||
222 | $response = $app->handle($request); |
||
223 | |||
224 | $this->assertEquals(200, $response->getStatusCode()); |
||
225 | |||
226 | $request = Request::create('/foo/bar/baz', 'HEAD'); |
||
227 | $response = $app->handle($request); |
||
228 | |||
229 | $this->assertEquals(200, $response->getStatusCode()); |
||
230 | } |
||
231 | |||
232 | /** |
||
233 | * This is just to show when defining routes that the trailing slash is |
||
234 | * required when the controller provider is mounted before any other routes. |
||
235 | * |
||
236 | * @dataProvider requestMethodProvider |
||
237 | * |
||
238 | * @param string $method |
||
239 | */ |
||
240 | View Code Duplication | public function testWillRespondWithNotFoundForRouteWithNoTrailingSlashWhenMountedFirst($method) |
|
265 | |||
266 | /** |
||
267 | * This is just to show when defining routes with no trailing slash before |
||
268 | * mounting the controller provider they should respond as expected. |
||
269 | * |
||
270 | * @dataProvider requestMethodProvider |
||
271 | * |
||
272 | * @param string $method |
||
273 | */ |
||
274 | View Code Duplication | public function testWillRespondWithOkForRouteWithNoTrailingSlashWhenMountedLast($method) |
|
275 | { |
||
276 | $app = new Application(); |
||
277 | |||
278 | $app->match('/foo', function () { |
||
279 | return 'hunter42'; |
||
280 | })->method($method); |
||
281 | |||
282 | $app->match('/foo/bar', function () { |
||
283 | return 'hunter42'; |
||
284 | })->method($method); |
||
285 | |||
286 | $app->register(new TrailingSlashControllerProvider()); |
||
287 | $app->mount('/', new TrailingSlashControllerProvider()); |
||
288 | |||
289 | $request = Request::create('/foo', $method); |
||
290 | $response = $app->handle($request); |
||
291 | |||
292 | $this->assertEquals(200, $response->getStatusCode()); |
||
293 | |||
294 | $request = Request::create('/foo/bar', $method); |
||
295 | $response = $app->handle($request); |
||
296 | |||
297 | $this->assertEquals(200, $response->getStatusCode()); |
||
298 | } |
||
299 | |||
300 | /** |
||
301 | * Test the case in which a request should have both query |
||
302 | * string params and body params |
||
303 | */ |
||
304 | public function testWillHandleQueryAndBodySeparately() |
||
331 | |||
332 | /** |
||
333 | * @param array $body |
||
334 | */ |
||
335 | private function assertRequestQuery(array $body) |
||
346 | } |
||
347 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.