ServiceTest::testFind()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 40
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

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