Passed
Push — master ( 727475...c2e18b )
by Igor
04:07
created

ServiceTest::testConstruct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 10
nc 1
nop 0
dl 0
loc 17
rs 9.9332
c 0
b 0
f 0
1
<?php
2
/** @noinspection PhpUnhandledExceptionInspection */
3
4
namespace SomeWork\Minjust\Tests\Unit;
5
6
use Exception;
7
use Generator;
8
use Iterator;
9
use PHPUnit\Framework\MockObject\MockObject;
10
use PHPUnit\Framework\TestCase;
11
use Psr\Http\Client\ClientExceptionInterface;
12
use ReflectionClass;
13
use ReflectionException;
14
use SomeWork\Minjust\Client;
15
use SomeWork\Minjust\Entity\DetailLawyer;
16
use SomeWork\Minjust\Entity\LawFormation;
17
use SomeWork\Minjust\Entity\Lawyer;
18
use SomeWork\Minjust\FindRequest;
19
use SomeWork\Minjust\FindResponse;
20
use SomeWork\Minjust\Parser\ParserInterface;
21
use SomeWork\Minjust\Service;
22
23
24
/**
25
 * @coversDefaultClass \SomeWork\Minjust\Service
26
 */
27
class ServiceTest extends TestCase
28
{
29
    /**
30
     * @covers ::__construct
31
     */
32
    public function testConstruct(): void
33
    {
34
        $client = $this->createMock(Client::class);
35
        $parser = $this->createMock(ParserInterface::class);
36
37
        $service = new Service($client, $parser);
38
39
        $ref = new ReflectionClass(Service::class);
40
41
        $privateClient = $ref->getProperty('client');
42
        $privateClient->setAccessible(true);
43
44
        $privateParser = $ref->getProperty('parser');
45
        $privateParser->setAccessible(true);
46
47
        $this->assertEquals($client, $privateClient->getValue($service));
48
        $this->assertEquals($parser, $privateParser->getValue($service));
49
    }
50
51
    /**
52
     * @covers ::findAll
53
     */
54
    public function testFindAll(): void
55
    {
56
        $request = new FindRequest();
57
58
        $fn = static function () {
59
            yield 1;
60
        };
61
62
        /**
63
         * @var MockObject|Service $service
64
         */
65
        $service = $this->createPartialMock(Service::class, ['findFromTo']);
66
67
        $service
68
            ->expects($this->once())
69
            ->method('findFromTo')
70
            ->with($request, 1, 0)
71
            ->willReturn($fn());
72
73
        $service->findAll($request);
74
    }
75
76
    /**
77
     * @covers ::find
78
     */
79
    public function testFind(): void
80
    {
81
        /**
82
         * @var ParserInterface|MockObject $parser
83
         * @var Service|MockObject         $service
84
         * @var Client|MockObject          $client
85
         */
86
        $lawyer = $this->generateLawyer();
87
88
        $response = (new FindResponse())
89
            ->addLawyer($lawyer)
90
            ->setPage(1)
91
            ->setTotalPage(1)
92
            ->setTotal(1);
93
94
        $client = $this->createMock(Client::class);
95
        $client
96
            ->method('list')
97
            ->willReturn('');
98
99
        $parser = $this->createMock(ParserInterface::class);
100
        $parser
101
            ->method('list')
102
            ->willReturn($response);
103
104
        $service = $this
105
            ->getMockBuilder(Service::class)
106
            ->onlyMethods(['getDetailLawyersGenerator'])
107
            ->setConstructorArgs([$client, $parser])
108
            ->getMock();
109
110
        $service
111
            ->method('getDetailLawyersGenerator')
112
            ->willReturn($this->generateDetailLawyerGenerator($lawyer));
113
114
        $response = $service->find(new FindRequest());
115
116
        $this->assertCount(1, $response->getLawyers());
117
        $this->assertInstanceOf(Lawyer::class, $response->getLawyers()[0]);
118
        $this->assertInstanceOf(Generator::class, $response->getDetailLawyers());
119
    }
120
121
    protected function generateLawyer(): Lawyer
122
    {
123
        try {
124
            $id = md5(random_bytes(16));
125
        } catch (Exception $exception) {
126
            $id = md5(microtime(true));
127
        }
128
129
        return (new Lawyer())
130
            ->setTerritorialSubject('Тестовая территория')
131
            ->setCertificateNumber('test/' . $id)
132
            ->setRegisterNumber('test/' . $id)
133
            ->setStatus('Тестовый статус')
134
            ->setFullName('Тестовый Тест Тестович')
135
            ->setUrl('/test/' . $id . '/');
136
    }
137
138
    /**
139
     * @param \SomeWork\Minjust\Entity\Lawyer $lawyer
140
     *
141
     * @return Generator
142
     */
143
    protected function generateDetailLawyerGenerator(Lawyer $lawyer): Generator
144
    {
145
        yield new DetailLawyer($lawyer);
146
    }
147
148
    /**
149
     * @covers ::findFromTo
150
     */
151
    public function testFindFromToOffsetForOnePage(): void
152
    {
153
        $lawyer = $this->generateLawyer();
154
155
        $response = (new FindResponse())
156
            ->setTotal(1)
157
            ->setTotalPage(1)
158
            ->setPage(1)
159
            ->addLawyer($lawyer)
160
            ->setDetailLawyersGenerator(
161
                $this->generateDetailLawyerGenerator($lawyer)
162
            );
163
164
        $service = $this
165
            ->createPartialMock(Service::class, ['find']);
166
        $service
167
            ->method('find')
168
            ->willReturn($response);
169
170
        $request = new FindRequest();
171
        $request->setOffset(1000);
172
173
        $response = $service->findFromTo($request, 1, 2);
174
        $this->assertInstanceOf(Generator::class, $response);
175
176
        foreach ($response as $lawyer) {
177
            $this->assertNotInstanceOf(DetailLawyer::class, $lawyer);
178
        }
179
        $this->assertEquals(0, $request->getOffset());
180
181
        $request->setFullData(true);
182
        $response = $service->findFromTo($request, 1, 1);
183
184
        $this->assertContainsOnlyInstancesOf(DetailLawyer::class, $response);
185
    }
186
187
    /**
188
     * @covers ::findFromTo
189
     * @dataProvider multipleProvider
190
     *
191
     * @param bool $isMultiple
192
     *
193
     * @throws ClientExceptionInterface
194
     */
195
    public function testFindFromToOffsetForMultiplePage(bool $isMultiple): void
196
    {
197
        $lawyerFirst = $this->generateLawyer();
198
        $lawyersSecond = $this->generateLawyer();
199
200
        $responseFirst = (new FindResponse())
201
            ->setTotal(1)
202
            ->setTotalPage(2)
203
            ->setPage(1)
204
            ->addLawyer($lawyerFirst)
205
            ->setDetailLawyersGenerator(
206
                $this->generateDetailLawyerGenerator($lawyerFirst)
207
            );
208
209
        $responseSecond = (new FindResponse())
210
            ->setTotal(1)
211
            ->setTotalPage(2)
212
            ->setPage(2)
213
            ->addLawyer($lawyersSecond)
214
            ->setDetailLawyersGenerator(
215
                $this->generateDetailLawyerGenerator($lawyersSecond)
216
            );
217
218
        $service = $this
219
            ->createPartialMock(Service::class, ['find']);
220
221
        $service
222
            ->expects($this->at(0))
223
            ->method('find')
224
            ->willReturn($responseFirst);
225
226
        $service
227
            ->expects($this->at(1))
228
            ->method('find')
229
            ->willReturn($responseSecond);
230
231
        $request = (new FindRequest())
232
            ->setMax(1);
233
234
        if (!$isMultiple) {
235
            $response = $service->findFromTo($request, 1, 2);
236
237
            $lawyer = $response->current();
238
            $this->assertInstanceOf(Lawyer::class, $lawyer);
239
            $this->assertEquals($lawyerFirst, $lawyer);
240
241
            $response->next();
242
            $this->assertEquals(1, $request->getOffset());
243
244
            $lawyer = $response->current();
245
            $this->assertInstanceOf(Lawyer::class, $lawyer);
246
            $this->assertEquals($lawyersSecond, $lawyer);
247
248
            $response->next();
249
            $this->assertFalse($response->valid());
250
251
            return;
252
        }
253
254
        $request->setFullData(true);
255
        $response = $service->findFromTo($request, 1, 2);
256
257
        $this->assertContainsOnlyInstancesOf(DetailLawyer::class, $response);
258
    }
259
260
    public function multipleProvider(): Iterator
261
    {
262
        yield [false];
263
        yield [true];
264
    }
265
266
    /**
267
     * @covers ::getDetailLawyersGenerator
268
     */
269
    public function testGetDetailLawyersGenerator(): void
270
    {
271
        $detailFirst = $this->generateDetailLawyer();
272
        $detailSecond = $this->generateDetailLawyer();
273
274
        $lawyerFirst = $this->generateLawyer();
275
        $lawyerSecond = $this->generateLawyer();
276
277
        $client = $this->createMock(Client::class);
278
        $client
279
            ->method('detail')
280
            ->willReturn('');
281
282
        $parser = $this->createMock(ParserInterface::class);
283
        $parser
284
            ->expects($this->at(0))
285
            ->method('detail')
286
            ->willReturn($detailFirst);
287
288
        $parser
289
            ->expects($this->at(1))
290
            ->method('detail')
291
            ->willReturn($detailSecond);
292
293
        $service = new Service($client, $parser);
294
        $generator = $this->invokeMethod($service, 'getDetailLawyersGenerator', [[$lawyerFirst, $lawyerSecond]]);
295
296
        $this->assertInstanceOf(Generator::class, $generator);
297
298
        /**
299
         * @var DetailLawyer $lawyer
300
         */
301
        $lawyer = $generator->current();
302
        $this->assertInstanceOf(DetailLawyer::class, $lawyer);
303
        $this->assertEquals($lawyerFirst->getUrl(), $lawyer->getUrl());
304
        $this->assertEquals($lawyerFirst->getTerritorialSubject(), $lawyer->getTerritorialSubject());
305
        $this->assertEquals($lawyerFirst->getStatus(), $lawyer->getStatus());
306
        $this->assertEquals($lawyerFirst->getCertificateNumber(), $lawyer->getCertificateNumber());
307
        $this->assertEquals($lawyerFirst->getRegisterNumber(), $lawyer->getRegisterNumber());
308
        $this->assertEquals($lawyerFirst->getFullName(), $lawyer->getFullName());
309
        $this->assertEquals($detailFirst, $lawyer);
310
311
        $generator->next();
312
        $lawyer = $generator->current();
313
        $this->assertInstanceOf(DetailLawyer::class, $lawyer);
314
        $this->assertEquals($lawyerSecond->getUrl(), $lawyer->getUrl());
315
        $this->assertEquals($lawyerSecond->getTerritorialSubject(), $lawyer->getTerritorialSubject());
316
        $this->assertEquals($lawyerSecond->getStatus(), $lawyer->getStatus());
317
        $this->assertEquals($lawyerSecond->getCertificateNumber(), $lawyer->getCertificateNumber());
318
        $this->assertEquals($lawyerSecond->getRegisterNumber(), $lawyer->getRegisterNumber());
319
        $this->assertEquals($lawyerSecond->getFullName(), $lawyer->getFullName());
320
        $this->assertEquals($detailSecond, $lawyer);
321
    }
322
323
    protected function generateDetailLawyer(?Lawyer $lawyer = null): DetailLawyer
324
    {
325
        try {
326
            $id = md5(random_bytes(16));
327
        } catch (Exception $exception) {
328
            $id = md5(microtime(true));
329
        }
330
331
        return (new DetailLawyer($lawyer))
332
            ->setChamberOfLaw('Палата ' . $id)
333
            ->setLawFormation(
334
                (new LawFormation())
335
                    ->setPhone('88004443459')
336
                    ->setAddress('г. Москва, ул. Беговая, д. 2')
337
                    ->setName('ООО "Бреви Ману" ID: ' . $id)
338
                    ->setEmail('[email protected]')
339
            );
340
    }
341
342
    /**
343
     * Call protected/private method of a class.
344
     *
345
     * @param object &$object     Instantiated object that we will run method on.
346
     * @param string  $methodName Method name to call
347
     * @param array   $parameters Array of parameters to pass into method.
348
     *
349
     * @return mixed Method return.
350
     * @throws ReflectionException
351
     */
352
    public function invokeMethod(&$object, $methodName, array $parameters = [])
353
    {
354
        $reflection = new ReflectionClass(get_class($object));
355
        $method = $reflection->getMethod($methodName);
356
        $method->setAccessible(true);
357
358
        return $method->invokeArgs($object, $parameters);
359
    }
360
361
    /**
362
     * @covers ::getDetailLawyersGenerator
363
     */
364
    public function testGetDetailLawyersGeneratorOnEmpty(): void
365
    {
366
        $client = $this->createMock(Client::class);
367
        $parser = $this->createMock(ParserInterface::class);
368
369
        $service = new Service($client, $parser);
370
371
        /**
372
         * @var Generator $generator
373
         */
374
        $generator = $this->invokeMethod($service, 'getDetailLawyersGenerator', [[]]);
375
        $this->assertInstanceOf(Generator::class, $generator);
376
        $this->assertFalse($generator->valid());
377
    }
378
}
379