Passed
Pull Request — master (#5)
by Alex
02:23
created

testFindOneByWillThrowEntityRepositoryExceptionIfUnableToPerformQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 19
c 1
b 0
f 0
dl 0
loc 29
rs 9.6333
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ArpTest\LaminasDoctrine\Repository;
6
7
use Arp\LaminasDoctrine\Repository\EntityRepository;
8
use Arp\Entity\EntityInterface;
9
use Arp\LaminasDoctrine\Repository\EntityRepositoryInterface;
10
use Arp\LaminasDoctrine\Repository\Exception\EntityRepositoryException;
11
use Arp\LaminasDoctrine\Repository\Persistence\PersistServiceInterface;
12
use Arp\LaminasDoctrine\Repository\Persistence\TransactionServiceInterface;
13
use Arp\LaminasDoctrine\Repository\Query\Exception\QueryServiceException;
14
use Arp\LaminasDoctrine\Repository\Query\QueryServiceInterface;
15
use PHPUnit\Framework\MockObject\MockObject;
16
use PHPUnit\Framework\TestCase;
17
use Psr\Log\LoggerInterface;
18
19
/**
20
 * @covers \Arp\LaminasDoctrine\Repository\EntityRepository
21
 */
22
final class EntityRepositoryTest extends TestCase
23
{
24
    /**
25
     * @var class-string<EntityInterface>
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<EntityInterface> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<EntityInterface>.
Loading history...
26
     */
27
    private string $entityName;
28
29
    /**
30
     * @var QueryServiceInterface<EntityInterface>&MockObject
31
     */
32
    private QueryServiceInterface $queryService;
33
34
    /**
35
     * @var PersistServiceInterface<EntityInterface>&MockObject
36
     */
37
    private PersistServiceInterface $persistService;
38
39
    /**
40
     * @var LoggerInterface&MockObject
41
     */
42
    private LoggerInterface $logger;
43
44
    public function setUp(): void
45
    {
46
        $this->entityName = EntityInterface::class;
47
        $this->queryService = $this->createMock(QueryServiceInterface::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(Arp\La...erviceInterface::class) of type PHPUnit\Framework\MockObject\MockObject is incompatible with the declared type Arp\LaminasDoctrine\Repo...y\QueryServiceInterface of property $queryService.

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..

Loading history...
48
        $this->persistService = $this->createMock(PersistServiceInterface::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(Arp\La...erviceInterface::class) of type PHPUnit\Framework\MockObject\MockObject is incompatible with the declared type Arp\LaminasDoctrine\Repo...PersistServiceInterface of property $persistService.

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..

Loading history...
49
        $this->logger = $this->createMock(LoggerInterface::class);
50
    }
51
52
    public function testImplementsEntityRepositoryInterface(): void
53
    {
54
        $repository = new EntityRepository(
55
            $this->entityName,
56
            $this->queryService,
57
            $this->persistService,
58
            $this->logger
59
        );
60
61
        $this->assertInstanceOf(EntityRepositoryInterface::class, $repository);
62
    }
63
64
    public function testImplementsTransactionServiceInterface(): void
65
    {
66
        $repository = new EntityRepository(
67
            $this->entityName,
68
            $this->queryService,
69
            $this->persistService,
70
            $this->logger
71
        );
72
73
        $this->assertInstanceOf(TransactionServiceInterface::class, $repository);
74
    }
75
76
    public function testGetClassName(): void
77
    {
78
        $repository = new EntityRepository(
79
            $this->entityName,
80
            $this->queryService,
81
            $this->persistService,
82
            $this->logger
83
        );
84
85
        $this->assertSame($this->entityName, $repository->getClassName());
86
    }
87
88
    /**
89
     * @throws EntityRepositoryException
90
     */
91
    public function testFindWillThrowEntityRepositoryExceptionIfUnableToPerformQuery(): void
92
    {
93
        $repository = new EntityRepository(
94
            $this->entityName,
95
            $this->queryService,
96
            $this->persistService,
97
            $this->logger
98
        );
99
100
        $id = 123;
101
102
        $exception = new QueryServiceException('This is a test message', 999);
103
104
        $this->queryService->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not exist on Arp\LaminasDoctrine\Repo...y\QueryServiceInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

104
        $this->queryService->/** @scrutinizer ignore-call */ 
105
                             expects($this->once())

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
105
            ->method('findOneById')
106
            ->with($id)
107
            ->willThrowException($exception);
108
109
        $errorMessage = sprintf('Unable to find entity of type \'%s\'', $this->entityName);
110
111
        $this->logger->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not exist on Psr\Log\LoggerInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

111
        $this->logger->/** @scrutinizer ignore-call */ 
112
                       expects($this->once())

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
112
            ->method('error')
113
            ->with($errorMessage, ['exception' => $exception, 'id' => $id]);
114
115
        $this->expectException(EntityRepositoryException::class);
116
        $this->expectExceptionMessage($errorMessage);
117
        $this->expectExceptionCode(999);
118
119
        $repository->find($id);
120
    }
121
122
    /**
123
     * @throws EntityRepositoryException
124
     */
125
    public function testFindWillReturnMatchedEntityById(): void
126
    {
127
        $repository = new EntityRepository(
128
            $this->entityName,
129
            $this->queryService,
130
            $this->persistService,
131
            $this->logger
132
        );
133
134
        $id = 123;
135
136
        /** @var EntityInterface&MockObject $entity */
137
        $entity = $this->createMock(EntityInterface::class);
138
139
        $this->queryService->expects($this->once())
140
            ->method('findOneById')
141
            ->with($id)
142
            ->willReturn($entity);
143
144
        $this->assertSame($entity, $repository->find($id));
145
    }
146
147
    /**
148
     * @throws EntityRepositoryException
149
     */
150
    public function testFindOneByIdWillThrowEntityRepositoryExceptionIfUnableToPerformQuery(): void
151
    {
152
        $repository = new EntityRepository(
153
            $this->entityName,
154
            $this->queryService,
155
            $this->persistService,
156
            $this->logger
157
        );
158
159
        $id = 456;
160
161
        $exception = new QueryServiceException('This is a test message', 111);
162
163
        $this->queryService->expects($this->once())
164
            ->method('findOneById')
165
            ->with($id)
166
            ->willThrowException($exception);
167
168
        $errorMessage = sprintf('Unable to find entity of type \'%s\'', $this->entityName);
169
170
        $this->logger->expects($this->once())
171
            ->method('error')
172
            ->with($errorMessage, ['exception' => $exception, 'id' => $id]);
173
174
        $this->expectException(EntityRepositoryException::class);
175
        $this->expectExceptionMessage($errorMessage);
176
        $this->expectExceptionCode(111);
177
178
        $repository->findOneById($id);
179
    }
180
181
    /**
182
     * @throws EntityRepositoryException
183
     */
184
    public function testFindOneByIdWillReturnMatchedEntityById(): void
185
    {
186
        $repository = new EntityRepository(
187
            $this->entityName,
188
            $this->queryService,
189
            $this->persistService,
190
            $this->logger
191
        );
192
193
        $id = 456;
194
195
        /** @var EntityInterface&MockObject $entity */
196
        $entity = $this->createMock(EntityInterface::class);
197
198
        $this->queryService->expects($this->once())
199
            ->method('findOneById')
200
            ->with($id)
201
            ->willReturn($entity);
202
203
        $this->assertSame($entity, $repository->findOneById($id));
204
    }
205
206
    /**
207
     * @throws EntityRepositoryException
208
     */
209
    public function testFindOneByWillThrowEntityRepositoryExceptionIfUnableToPerformQuery(): void
210
    {
211
        $repository = new EntityRepository(
212
            $this->entityName,
213
            $this->queryService,
214
            $this->persistService,
215
            $this->logger
216
        );
217
218
        $criteria = ['foo' => 'bar'];
219
220
        $exception = new QueryServiceException('This is a test message for ' . __FUNCTION__, 777);
221
222
        $this->queryService->expects($this->once())
223
            ->method('findOne')
224
            ->with($criteria)
225
            ->willThrowException($exception);
226
227
        $errorMessage = sprintf('Unable to find entity of type \'%s\'', $this->entityName);
228
229
        $this->logger->expects($this->once())
230
            ->method('error')
231
            ->with($errorMessage, ['exception' => $exception, 'criteria' => $criteria]);
232
233
        $this->expectException(EntityRepositoryException::class);
234
        $this->expectExceptionMessage($errorMessage);
235
        $this->expectExceptionCode(777);
236
237
        $repository->findOneBy($criteria);
238
    }
239
240
    /**
241
     * @throws EntityRepositoryException
242
     */
243
    public function testFindOneByWillReturnMatchedEntityByCriteria(): void
244
    {
245
        $repository = new EntityRepository(
246
            $this->entityName,
247
            $this->queryService,
248
            $this->persistService,
249
            $this->logger
250
        );
251
252
        $criteria = [
253
            'test' => 'hello',
254
            'a' => 'z',
255
            'foo' => 123,
256
        ];
257
258
        /** @var EntityInterface&MockObject $entity */
259
        $entity = $this->createMock(EntityInterface::class);
260
261
        $this->queryService->expects($this->once())
262
            ->method('findOne')
263
            ->with($criteria)
264
            ->willReturn($entity);
265
266
        $this->assertSame($entity, $repository->findOneBy($criteria));
267
    }
268
}
269