Completed
Pull Request — master (#81)
by John
03:37
created

ExceptionListenerTest::setLogger()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 1
eloc 5
nc 1
nop 2
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\SwaggerBundle\EventListener\ExceptionListener;
12
use KleijnWeb\SwaggerBundle\Response\Error\LogRefBuilder;
13
use KleijnWeb\SwaggerBundle\Response\ErrorResponseFactory;
14
use Psr\Log\LoggerInterface;
15
use Psr\Log\LogLevel;
16
use Symfony\Component\HttpFoundation\Request;
17
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
18
19
/**
20
 * @author John Kleijn <[email protected]>
21
 */
22
class ExceptionListenerTest extends \PHPUnit_Framework_TestCase
23
{
24
    /**
25
     * @var GetResponseForExceptionEvent
26
     */
27
    private $event;
28
29
    /**
30
     * @var \ReflectionProperty
31
     */
32
    private $codeProperty;
33
34
    /**
35
     * @var \Exception
36
     */
37
    private $exception;
38
39
    /**
40
     * @var Request
41
     */
42
    private $request;
43
44
    /**
45
     * @var LoggerInterface
46
     */
47
    private $logger;
48
49
    /**
50
     * @var ExceptionListener
51
     */
52
    private $exceptionListener;
53
54
    /**
55
     * Set up mocking
56
     */
57
    protected function setUp()
58
    {
59
        $this->event = $this
60
            ->getMockBuilder(GetResponseForExceptionEvent::class)
61
            ->disableOriginalConstructor()
62
            ->setMethods(['getException', 'getRequest'])
63
            ->getMock();
64
65
        $this->exception    = new \Exception("Mary had a little lamb");
66
        $reflection         = new \ReflectionClass($this->exception);
67
        $codeProperty       = $reflection->getProperty('code');
68
        $this->codeProperty = $codeProperty;
69
        $this->codeProperty->setAccessible(true);
70
        $attributes    = [
71
            '_swagger.file' => '/foo/bar'
72
        ];
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 ErrorResponseFactory $errorResponseFactory */
86
        $this->errorResponseFactory = $errorResponseFactory = $this
0 ignored issues
show
Bug introduced by
The property errorResponseFactory does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
87
            ->getMockBuilder(ErrorResponseFactory::class)
88
            ->disableOriginalConstructor()
89
            ->getMock();
90
91
        /** @var LogRefBuilder $logRefBuilder */
92
        $lofRefBuilderMock = $logRefBuilder = $this->getMockForAbstractClass(LogRefBuilder::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
    /**
100
     * @test
101
     */
102 View Code Duplication
    public function willLogExceptionsWith4xxCodesAsBadRequestNotices()
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...
103
    {
104
        for ($i = 0; $i < 99; $i++) {
105
            $logger = $this->getMockForAbstractClass(LoggerInterface::class);
106
            $logger
107
                ->expects($this->once())
108
                ->method('log')
109
                ->with(LogLevel::NOTICE, $this->stringStartsWith('Bad Request'));
110
111
            /** @var LoggerInterface $logger */
112
            $this->setLogger($this->exceptionListener, $logger);
113
            $this->codeProperty->setValue($this->exception, 400 + $i);
114
            $this->exceptionListener->onKernelException($this->event);
115
        }
116
    }
117
118
    /**
119
     * @test
120
     */
121 View Code Duplication
    public function willLogExceptionsWith5xxCodesAsRuntimeErrors()
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...
122
    {
123
        for ($i = 0; $i < 99; $i++) {
124
            $logger = $this->getMockForAbstractClass(LoggerInterface::class);
125
            $logger
126
                ->expects($this->once())
127
                ->method('log')
128
                ->with(LogLevel::ERROR, $this->stringStartsWith('Internal Server Error'));
129
130
            /** @var LoggerInterface $logger */
131
            $this->setLogger($this->exceptionListener, $logger);
132
            $this->codeProperty->setValue($this->exception, 500 + $i);
133
            $this->exceptionListener->onKernelException($this->event);
134
        }
135
    }
136
137
    /**
138
     * @test
139
     */
140
    public function willLogExceptionsWithUnexpectedCodesAsCriticalErrors()
141
    {
142
        $sample = [4096, 777, 22, 5, 0];
143
        foreach ($sample as $code) {
144
            $logger = $this->getMockForAbstractClass(LoggerInterface::class);
145
            $logger
146
                ->expects($this->once())
147
                ->method('log')
148
                ->with(LogLevel::CRITICAL, $this->stringStartsWith('Internal Server Error'));
149
150
            /** @var LoggerInterface $logger */
151
            $this->setLogger($this->exceptionListener, $logger);
152
            $this->codeProperty->setValue($this->exception, $code);
153
            $this->exceptionListener->onKernelException($this->event);
154
        }
155
    }
156
157
    /**
158
     * @param ExceptionListener $exceptionListener
159
     * @param LoggerInterface   $logger
160
     */
161
    private function setLogger(ExceptionListener $exceptionListener, LoggerInterface $logger)
162
    {
163
        $reflection = new \ReflectionObject($exceptionListener);
164
        $property   = $reflection->getProperty('logger');
165
        $property->setAccessible(true);
166
        $property->setValue($exceptionListener, $logger);
167
    }
168
}
169