Completed
Push — master ( 170fde...562033 )
by Jan
03:08
created

ApiClientTest::getRequests()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 83
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 83
rs 8.7468
cc 1
eloc 40
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace SlevomatCsobGateway\Api;
4
5
use SlevomatCsobGateway\Crypto\CryptoService;
6
use SlevomatCsobGateway\Crypto\SignatureDataFormatter;
7
8
class ApiClientTest extends \PHPUnit_Framework_TestCase
9
{
10
11
	const API_URL = 'http://foo.csob.cz';
12
13
	public function getRequests()
14
	{
15
		return [
16
			[
17
				new HttpMethod(HttpMethod::GET),
18
				'fooUrl/{dttm}/{signature}',
19
				'fooUrl/' . date('YmdHis') . '/signature',
20
				[],
21
				null,
22
				[
23
					'bar' => 2,
24
				],
25
				new ResponseCode(ResponseCode::S200_OK),
26
				[
27
					'header' => 'value',
28
				],
29
			],
30
			[
31
				new HttpMethod(HttpMethod::GET),
32
				'fooUrl/{fooId}/{dttm}/{signature}',
33
				'fooUrl/3/' . date('YmdHis') . '/signature',
34
				[
35
					'fooId' => 3,
36
				],
37
				null,
38
				[
39
					'bar' => 2,
40
				],
41
				new ResponseCode(ResponseCode::S200_OK),
42
				[
43
					'header' => 'value',
44
				],
45
			],
46
			[
47
				new HttpMethod(HttpMethod::POST),
48
				'fooUrl',
49
				'fooUrl',
50
				[
51
					'foo' => 1,
52
				],
53
				[
54
					'foo' => 1,
55
				],
56
				[
57
					'bar' => 2,
58
				],
59
				new ResponseCode(ResponseCode::S200_OK),
60
				[
61
					'header' => 'value',
62
				],
63
			],
64
			[
65
				new HttpMethod(HttpMethod::PUT),
66
				'fooUrl',
67
				'fooUrl',
68
				[
69
					'foo' => 1,
70
				],
71
				[
72
					'foo' => 1,
73
				],
74
				[
75
					'bar' => 2,
76
				],
77
				new ResponseCode(ResponseCode::S200_OK),
78
				[
79
					'header' => 'value',
80
				],
81
			],
82
			[
83
				new HttpMethod(HttpMethod::GET),
84
				'fooUrl/{dttm}/{signature}',
85
				'fooUrl/' . date('YmdHis') . '/signature',
86
				[],
87
				null,
88
				null,
89
				new ResponseCode(ResponseCode::S303_SEE_OTHER),
90
				[
91
					'header' => 'value',
92
				],
93
			],
94
		];
95
	}
96
97
	/**
98
	 * @param HttpMethod $httpMethod
99
	 * @param string $url
100
	 * @param string $expectedUrl
101
	 * @param mixed[] $requestData
102
	 * @param mixed[]|null $expectedRequestData
103
	 * @param mixed[]|null $responseData
104
	 * @param ResponseCode $responseCode
105
	 * @param mixed[] $responseHeaders
106
	 *
107
	 * @dataProvider getRequests
108
	 */
109
	public function testRequests(HttpMethod $httpMethod, $url, $expectedUrl, array $requestData, array $expectedRequestData = null, $responseData, ResponseCode $responseCode, array $responseHeaders)
110
	{
111
		self::markTestIncomplete('Contains imprecise DateTime handling');
112
		$currentTime = new \DateTimeImmutable();
113
114
		$cryptoService = $this->getMockBuilder(CryptoService::class)
115
			->disableOriginalConstructor()
116
			->getMock();
117
118
		$cryptoService->expects(self::any())
119
			->method('signData')
120
			->willReturn('signature');
121
122
		$cryptoService->expects(self::any())
123
			->method('verifyData')
124
			->willReturn(true);
125
126
		/** @var CryptoService $cryptoService */
127
		$apiClientDriver = $this->getMockBuilder(ApiClientDriver::class)
128
			->getMock();
129
130
		if ($httpMethod->equalsValue(HttpMethod::GET)) {
131
			$apiClientDriver->expects(self::once())
132
				->method('request')
133
				->with($httpMethod, self::API_URL . '/' . $expectedUrl, $expectedRequestData)
134
				->willReturn(new Response(
135
					$responseCode,
136
					($responseData ? $responseData : []) + [
137
						'signature' => 'signature',
138
					],
139
					$responseHeaders
140
				));
141
142
		} else {
143
			$apiClientDriver->expects(self::once())
144
				->method('request')
145
				->with($httpMethod, self::API_URL . '/' . $expectedUrl, $expectedRequestData + [
146
						'signature' => $cryptoService->signData($requestData, new SignatureDataFormatter([])),
147
						'dttm' => $currentTime->format('YmdHis'),
148
					])
149
				->willReturn(new Response(
150
					$responseCode,
151
					($responseData ? $responseData : []) + [
152
						'signature' => 'signature',
153
					],
154
					$responseHeaders
155
				));
156
		}
157
158
		/** @var ApiClientDriver $apiClientDriver */
159
		$apiClient = new ApiClient($apiClientDriver, $cryptoService, self::API_URL);
160
161
		if ($httpMethod->equalsValue(HttpMethod::GET)) {
162
			$response = $apiClient->get($url, $requestData, new SignatureDataFormatter([]), new SignatureDataFormatter([]));
163
164
		} elseif ($httpMethod->equalsValue(HttpMethod::POST)) {
165
			$response = $apiClient->post($url, $requestData, new SignatureDataFormatter([]), new SignatureDataFormatter([]));
166
167
		} else {
168
			$response = $apiClient->put($url, $requestData, new SignatureDataFormatter([]), new SignatureDataFormatter([]));
169
		}
170
171
		$this->assertInstanceOf(Response::class, $response);
172
		$this->assertSame($responseCode->getValue(), $response->getResponseCode()->getValue());
173
		$this->assertEquals($responseHeaders, $response->getHeaders());
174
		$this->assertEquals($responseData, $response->getData());
175
	}
176
177
	public function getTestExceptions()
178
	{
179
		return [
180
			[
181
				new Response(
182
					new ResponseCode(ResponseCode::S400_BAD_REQUEST),
183
					[]
184
				),
185
				BadRequestException::class,
186
			],
187
			[
188
				new Response(
189
					new ResponseCode(ResponseCode::S403_FORBIDDEN),
190
					[]
191
				),
192
				ForbiddenException::class,
193
			],
194
			[
195
				new Response(
196
					new ResponseCode(ResponseCode::S404_NOT_FOUND),
197
					[]
198
				),
199
				NotFoundException::class,
200
			],
201
			[
202
				new Response(
203
					new ResponseCode(ResponseCode::S405_METHOD_NOT_ALLOWED),
204
					[]
205
				),
206
				MethodNotAllowedException::class,
207
			],
208
			[
209
				new Response(
210
					new ResponseCode(ResponseCode::S429_TOO_MANY_REQUESTS),
211
					[]
212
				),
213
				TooManyRequestsException::class,
214
			],
215
			[
216
				new Response(
217
					new ResponseCode(ResponseCode::S503_SERVICE_UNAVAILABLE),
218
					[]
219
				),
220
				ServiceUnavailableException::class,
221
			],
222
			[
223
				new Response(
224
					new ResponseCode(ResponseCode::S500_INTERNAL_ERROR),
225
					[]
226
				),
227
				InternalErrorException::class,
228
			],
229
		];
230
	}
231
232
	/**
233
	 * @param Response $response
234
	 * @param string $expectedExceptionClass
235
	 *
236
	 * @dataProvider getTestExceptions
237
	 */
238
	public function testExceptions(Response $response, $expectedExceptionClass)
239
	{
240
		$cryptoService = $this->getMockBuilder(CryptoService::class)
241
			->disableOriginalConstructor()
242
			->getMock();
243
244
		$cryptoService->expects(self::once())
245
			->method('signData')
246
			->willReturn('signature');
247
248
		$cryptoService->expects(self::any())
249
			->method('verifyData')
250
			->willReturn(true);
251
252
		$apiClientDriver = $this->getMockBuilder(ApiClientDriver::class)
253
			->getMock();
254
255
		$apiClientDriver->expects(self::once())
256
			->method('request')
257
			->willReturn($response);
258
259
		/** @var CryptoService $cryptoService */
260
		/** @var ApiClientDriver $apiClientDriver */
261
		$apiClient = new ApiClient($apiClientDriver, $cryptoService);
262
263
		try {
264
			$apiClient->get('foo/{dttm}/{signature}', [], new SignatureDataFormatter([]), new SignatureDataFormatter([]));
265
			$this->fail();
266
267
		} catch (RequestException $e) {
268
			$this->assertInstanceOf($expectedExceptionClass, $e);
269
			$this->assertSame($response, $e->getResponse());
270
		}
271
	}
272
273
	public function testMissingSignature()
274
	{
275
		$response = new Response(
276
			new ResponseCode(ResponseCode::S200_OK),
277
			[]
278
		);
279
280
		$cryptoService = $this->getMockBuilder(CryptoService::class)
281
			->disableOriginalConstructor()
282
			->getMock();
283
284
		$cryptoService->expects(self::once())
285
			->method('signData')
286
			->willReturn('signature');
287
288
		$apiClientDriver = $this->getMockBuilder(ApiClientDriver::class)
289
			->getMock();
290
291
		$apiClientDriver->expects(self::once())
292
			->method('request')
293
			->willReturn($response);
294
295
		/** @var CryptoService $cryptoService */
296
		/** @var ApiClientDriver $apiClientDriver */
297
		$apiClient = new ApiClient($apiClientDriver, $cryptoService);
298
299
		try {
300
			$apiClient->get('foo/{dttm}/{signature}', [], new SignatureDataFormatter([]), new SignatureDataFormatter([]));
301
			$this->fail();
302
303
		} catch (InvalidSignatureException $e) {
304
			$this->assertSame($response, $e->getResponse());
305
		}
306
	}
307
308
	public function testInvalidSignature()
309
	{
310
		$response = new Response(
311
			new ResponseCode(ResponseCode::S200_OK),
312
			[
313
				'signature' => 'invalidSignature',
314
			]
315
		);
316
317
		$cryptoService = $this->getMockBuilder(CryptoService::class)
318
			->disableOriginalConstructor()
319
			->getMock();
320
321
		$cryptoService->expects(self::once())
322
			->method('signData')
323
			->willReturn('signature');
324
325
		$cryptoService->expects(self::any())
326
			->method('verifyData')
327
			->willReturn(false);
328
329
		$apiClientDriver = $this->getMockBuilder(ApiClientDriver::class)
330
			->getMock();
331
332
		$apiClientDriver->expects(self::once())
333
			->method('request')
334
			->willReturn($response);
335
336
		/** @var CryptoService $cryptoService */
337
		/** @var ApiClientDriver $apiClientDriver */
338
		$apiClient = new ApiClient($apiClientDriver, $cryptoService);
339
340
		try {
341
			$apiClient->get('foo/{dttm}/{signature}', [], new SignatureDataFormatter([]), new SignatureDataFormatter([]));
342
			$this->fail();
343
344
		} catch (InvalidSignatureException $e) {
345
			$this->assertSame($response, $e->getResponse());
346
		}
347
	}
348
349
	public function testCreateResponseByData()
350
	{
351
		$data = [
352
			'signature' => 'abc',
353
			'foo' => 123,
354
			'bar' => 456,
355
		];
356
357
		$cryptoService = $this->getMockBuilder(CryptoService::class)
358
			->disableOriginalConstructor()
359
			->getMock();
360
361
		$cryptoService->expects(self::any())
362
			->method('verifyData')
363
			->willReturn(true);
364
365
		$apiClientDriver = $this->getMockBuilder(ApiClientDriver::class)
366
			->getMock();
367
368
		/** @var CryptoService $cryptoService */
369
		/** @var ApiClientDriver $apiClientDriver */
370
		$apiClient = new ApiClient($apiClientDriver, $cryptoService);
371
372
		$response = $apiClient->createResponseByData($data, new SignatureDataFormatter([]));
373
374
		unset($data['signature']);
375
376
		$this->assertInstanceOf(Response::class, $response);
377
		$this->assertSame(ResponseCode::S200_OK, $response->getResponseCode()->getValue());
378
		$this->assertEquals([], $response->getHeaders());
379
		$this->assertEquals($data, $response->getData());
380
	}
381
382
}
383