Completed
Push — master ( e9ab7e...fd313c )
by John
01:50
created

testWillLogExceptionsWith5xxCodesAsRuntimeErrors()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 10

Duplication

Lines 15
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 15
loc 15
rs 9.4285
c 1
b 0
f 0
cc 2
eloc 10
nc 2
nop 0
1
<?php declare(strict_types = 1);
2
/*
3
 * This file is part of the KleijnWeb\SwaggerBundle package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace KleijnWeb\SwaggerBundle\Tests\EventListener;
10
11
use KleijnWeb\PhpApi\RoutingBundle\Routing\RequestMeta;
12
use KleijnWeb\SwaggerBundle\EventListener\ExceptionListener;
13
use KleijnWeb\SwaggerBundle\EventListener\Response\Error\LogRefBuilderInterface;
14
use KleijnWeb\SwaggerBundle\EventListener\Response\ErrorResponseFactoryInterface;
15
use Psr\Log\LoggerInterface;
16
use Psr\Log\LogLevel;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
19
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
20
21
/**
22
 * @author John Kleijn <[email protected]>
23
 */
24
class ExceptionListenerTest extends \PHPUnit_Framework_TestCase
25
{
26
    /**
27
     * @var GetResponseForExceptionEvent
28
     */
29
    private $event;
30
31
    /**
32
     * @var \ReflectionProperty
33
     */
34
    private $codeProperty;
35
36
    /**
37
     * @var \Exception
38
     */
39
    private $exception;
40
41
    /**
42
     * @var Request
43
     */
44
    private $request;
45
46
    /**
47
     * @var LoggerInterface
48
     */
49
    private $logger;
50
51
    /**
52
     * @var ExceptionListener
53
     */
54
    private $exceptionListener;
55
56
    /**
57
     * Set up mocking
58
     */
59
    protected function setUp()
60
    {
61
        $this->event = $this
62
            ->getMockBuilder(GetResponseForExceptionEvent::class)
63
            ->disableOriginalConstructor()
64
            ->setMethods(['getException', 'getRequest', 'setResponse'])
65
            ->getMock();
66
67
        $this->exception    = new \Exception("Mary had a little lamb");
68
        $reflection         = new \ReflectionClass($this->exception);
69
        $codeProperty       = $reflection->getProperty('code');
70
        $this->codeProperty = $codeProperty;
71
        $this->codeProperty->setAccessible(true);
72
        $attributes    = [RequestMeta::ATTRIBUTE_URI => '/foo/bar'];
73
        $this->request = new Request($query = [], $request = [], $attributes);
74
75
        $this->event
76
            ->expects($this->any())
77
            ->method('getException')
78
            ->willReturn($this->exception);
79
80
        $this->event
81
            ->expects($this->any())
82
            ->method('getRequest')
83
            ->willReturn($this->request);
84
85
        /** @var ErrorResponseFactoryInterface $errorResponseFactory */
86
        $errorResponseFactory = $this
87
            ->getMockBuilder(ErrorResponseFactoryInterface::class)
88
            ->disableOriginalConstructor()
89
            ->getMock();
90
91
        /** @var LogRefBuilderInterface $logRefBuilder */
92
        $lofRefBuilderMock = $logRefBuilder = $this->getMockForAbstractClass(LogRefBuilderInterface::class);
93
        $lofRefBuilderMock->expects($this->any())->method('create')->willReturn((string)rand());
94
95
        $this->logger            = $this->getMockForAbstractClass(LoggerInterface::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getMockForAbstrac...LoggerInterface::class) of type object<PHPUnit_Framework_MockObject_MockObject> is incompatible with the declared type object<Psr\Log\LoggerInterface> of property $logger.

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...
96
        $this->exceptionListener = new ExceptionListener($errorResponseFactory, $logRefBuilder, $this->logger);
97
    }
98
99 View Code Duplication
    public function testWillNotHandleIfNoDocumentUriInAttributesAndNotHttpException()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
100
    {
101
        $event = $this
102
            ->getMockBuilder(GetResponseForExceptionEvent::class)
103
            ->disableOriginalConstructor()
104
            ->setMethods(['getException', 'getRequest', 'setResponse'])
105
            ->getMock();
106
107
        $event
108
            ->expects($this->any())
109
            ->method('getException')
110
            ->willReturn(new \Exception("Mary had a little lamb"))
111
        ;
112
113
        $event
114
            ->expects($this->any())
115
            ->method('getRequest')
116
            ->willReturn(new Request())
117
        ;
118
119
        $event
120
            ->expects($this->never())
121
            ->method('setResponse')
122
        ;
123
124
        /** @var GetResponseForExceptionEvent $event */
125
        $this->exceptionListener->onKernelException($event);
126
    }
127
128 View Code Duplication
    public function testWillHandleIfNoDocumentUriInAttributesButHttpException()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129
    {
130
        $event = $this
131
            ->getMockBuilder(GetResponseForExceptionEvent::class)
132
            ->disableOriginalConstructor()
133
            ->setMethods(['getException', 'getRequest', 'setResponse'])
134
            ->getMock();
135
136
        $event
137
            ->expects($this->any())
138
            ->method('getException')
139
            ->willReturn(new NotFoundHttpException())
140
        ;
141
142
        $event
143
            ->expects($this->any())
144
            ->method('getRequest')
145
            ->willReturn(new Request())
146
        ;
147
148
        $event
149
            ->expects($this->once())
150
            ->method('setResponse')
151
        ;
152
153
        /** @var GetResponseForExceptionEvent $event */
154
        $this->exceptionListener->onKernelException($event);
155
    }
156
157 View Code Duplication
    public function testWillLogExceptionsWith4xxCodesAsBadRequestNotices()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
158
    {
159
        for ($i = 0; $i < 99; $i++) {
160
            $logger = $this->getMockForAbstractClass(LoggerInterface::class);
161
            $logger
162
                ->expects($this->once())
163
                ->method('log')
164
                ->with(LogLevel::NOTICE, $this->stringStartsWith('Bad Request'));
165
166
            /** @var LoggerInterface $logger */
167
            $this->setLogger($this->exceptionListener, $logger);
168
            $this->codeProperty->setValue($this->exception, 400 + $i);
169
            $this->exceptionListener->onKernelException($this->event);
170
        }
171
    }
172
173 View Code Duplication
    public function testWillLogExceptionsWith5xxCodesAsRuntimeErrors()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
174
    {
175
        for ($i = 0; $i < 99; $i++) {
176
            $logger = $this->getMockForAbstractClass(LoggerInterface::class);
177
            $logger
178
                ->expects($this->once())
179
                ->method('log')
180
                ->with(LogLevel::ERROR, $this->stringStartsWith('Internal Server Error'));
181
182
            /** @var LoggerInterface $logger */
183
            $this->setLogger($this->exceptionListener, $logger);
184
            $this->codeProperty->setValue($this->exception, 500 + $i);
185
            $this->exceptionListener->onKernelException($this->event);
186
        }
187
    }
188
189
    public function testWillLogExceptionsWithUnexpectedCodesAsCriticalErrors()
190
    {
191
        $sample = [4096, 777, 22, 5, 0];
192
        foreach ($sample as $code) {
193
            $logger = $this->getMockForAbstractClass(LoggerInterface::class);
194
            $logger
195
                ->expects($this->once())
196
                ->method('log')
197
                ->with(LogLevel::CRITICAL, $this->stringStartsWith('Internal Server Error'));
198
199
            /** @var LoggerInterface $logger */
200
            $this->setLogger($this->exceptionListener, $logger);
201
            $this->codeProperty->setValue($this->exception, $code);
202
            $this->exceptionListener->onKernelException($this->event);
203
        }
204
    }
205
206
    /**
207
     * @param ExceptionListener $exceptionListener
208
     * @param LoggerInterface   $logger
209
     */
210
    private function setLogger(ExceptionListener $exceptionListener, LoggerInterface $logger)
211
    {
212
        $reflection = new \ReflectionObject($exceptionListener);
213
        $property   = $reflection->getProperty('logger');
214
        $property->setAccessible(true);
215
        $property->setValue($exceptionListener, $logger);
216
    }
217
}
218