Passed
Push — master ( 671ba2...2c67da )
by Paweł
03:40
created

KernelTest::setUpKernel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 7
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 12
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gorynych\Tests\Http;
6
7
use DG\BypassFinals;
8
use Gorynych\Http\Dto\ProblemDetails;
9
use Gorynych\Http\Exception\NotAcceptableHttpException;
10
use Gorynych\Http\Formatter\FormatterFactory;
11
use Gorynych\Http\Formatter\FormatterInterface;
12
use Gorynych\Http\Kernel;
13
use Gorynych\Http\Routing\Router;
14
use Gorynych\Operation\ResourceOperationInterface;
15
use PHPUnit\Framework\MockObject\MockObject;
16
use PHPUnit\Framework\TestCase;
17
use Symfony\Component\HttpFoundation\JsonResponse;
18
use Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\HttpFoundation\Response;
20
21
BypassFinals::enable();
22
23
class KernelTest extends TestCase
24
{
25
    /** @var ResourceOperationInterface|MockObject */
26
    private $operationMock;
27
    /** @var FormatterInterface|MockObject */
28
    private $formatterMock;
29
    /** @var FormatterFactory|MockObject */
30
    private $formatterFactoryMock;
31
    /** @var Router|MockObject */
32
    private $routerMock;
33
34
    public function setUp(): void
35
    {
36
        $this->operationMock = $this->createMock(ResourceOperationInterface::class);
37
        $this->formatterMock = $this->createMock(FormatterInterface::class);
38
        $this->formatterFactoryMock = $this->createMock(FormatterFactory::class);
39
        $this->routerMock = $this->createMock(Router::class);
40
    }
41
42
    public function testHandlesRequest(): void
43
    {
44
        $request = $this->createMock(Request::class);
45
        $request->method('getAcceptableContentTypes')->willReturn(['application/json']);
46
47
        $responseExpected = new JsonResponse('foo', Response::HTTP_OK);
48
49
        $this->operationMock
50
            ->expects($this->once())
51
            ->method('handle')
52
            ->with($request)
53
            ->willReturn(['foo']);
54
        $this->operationMock
55
            ->expects($this->once())
56
            ->method('getResponseStatus')
57
            ->willReturn(Response::HTTP_OK);
58
59
        $this->formatterMock
60
            ->expects($this->once())
61
            ->method('format')
62
            ->with(['foo'], Response::HTTP_OK)
63
            ->willReturn($responseExpected);
64
65
        $this->routerMock
66
            ->expects($this->once())
67
            ->method('findOperation')
68
            ->with($request)
69
            ->willReturn($this->operationMock);
70
71
        $this->formatterFactoryMock
72
            ->expects($this->once())
73
            ->method('create')
74
            ->with(...$request->getAcceptableContentTypes())
75
            ->willReturn($this->formatterMock);
76
77
        $response = $this->setUpKernel()->boot()->handleRequest($request);
78
79
        $this->assertSame($responseExpected->getContent(), $response->getContent());
80
        $this->assertSame($responseExpected->getStatusCode(), $response->getStatusCode());
81
    }
82
83
    public function testThrowsExceptionInDevEnvironment(): void
84
    {
85
        $this->expectException(\RuntimeException::class);
86
87
        $request = $this->createMock(Request::class);
88
        $request->method('getAcceptableContentTypes')->willReturn(['application/json']);
89
90
        $this->operationMock
91
            ->expects($this->once())
92
            ->method('handle')
93
            ->with($request)
94
            ->willThrowException(new \RuntimeException());
95
96
        $this->routerMock
97
            ->expects($this->once())
98
            ->method('findOperation')
99
            ->with($request)
100
            ->willReturn($this->operationMock);
101
102
        $this->formatterFactoryMock
103
            ->expects($this->once())
104
            ->method('create')
105
            ->with(...$request->getAcceptableContentTypes())
106
            ->willReturn($this->formatterMock);
107
108
        $this->setUpKernel()->boot('dev')->handleRequest($request);
109
    }
110
111
    public function testReturnsProblemDetailsInProdEnvironment(): void
112
    {
113
        $request = $this->createMock(Request::class);
114
        $request->method('getAcceptableContentTypes')->willReturn(['application/json']);
115
116
        $exception = new \RuntimeException('test');
117
        $problemDetails = ProblemDetails::fromThrowable($exception);
118
        $responseExpected = new JsonResponse($problemDetails, Response::HTTP_INTERNAL_SERVER_ERROR);
119
120
        $this->operationMock
121
            ->expects($this->once())
122
            ->method('handle')
123
            ->with($request)
124
            ->willThrowException($exception);
125
126
        $this->formatterMock
127
            ->expects($this->once())
128
            ->method('format')
129
            ->with($problemDetails, Response::HTTP_INTERNAL_SERVER_ERROR)
130
            ->willReturn($responseExpected);
131
132
        $this->routerMock
133
            ->expects($this->once())
134
            ->method('findOperation')
135
            ->with($request)
136
            ->willReturn($this->operationMock);
137
138
        $this->formatterFactoryMock
139
            ->expects($this->once())
140
            ->method('create')
141
            ->with(...$request->getAcceptableContentTypes())
142
            ->willReturn($this->formatterMock);
143
144
        $response = $this->setUpKernel()->boot('prod')->handleRequest($request);
145
146
        $this->assertSame($responseExpected->getContent(), $response->getContent());
147
        $this->assertSame($responseExpected->getStatusCode(), $response->getStatusCode());
148
    }
149
150
    public function testReturnsNotAcceptableResponse(): void
151
    {
152
        $request = $this->createMock(Request::class);
153
        $request->method('getAcceptableContentTypes')->willReturn(['application/json']);
154
155
        $responseExpected = new Response('test', Response::HTTP_NOT_ACCEPTABLE);
156
157
        $this->formatterFactoryMock
158
            ->expects($this->once())
159
            ->method('create')
160
            ->with(...$request->getAcceptableContentTypes())
161
            ->willThrowException(new NotAcceptableHttpException('test'));
162
163
        $response = $this->setUpKernel()->boot()->handleRequest($request);
164
165
        $this->assertSame($responseExpected->getContent(), $response->getContent());
166
        $this->assertSame($responseExpected->getStatusCode(), $response->getStatusCode());
167
    }
168
169
    /**
170
     * @return Kernel|MockObject
171
     */
172
    private function setUpKernel()
173
    {
174
        /** @var Kernel|MockObject $kernel */
175
        $kernel = $this->getMockBuilder(Kernel::class)
176
            ->onlyMethods(['getRouter', 'getFormatterFactory', 'initializeContainer', 'getConfigLocator', 'loadConfiguration'])
177
            ->getMock();
178
179
        $kernel->expects($this->once())->method('initializeContainer');
180
        $kernel->expects($this->any())->method('getFormatterFactory')->willReturn($this->formatterFactoryMock);
181
        $kernel->expects($this->any())->method('getRouter')->willReturn($this->routerMock);
182
183
        return $kernel;
184
    }
185
}
186