Completed
Push — master ( 236a45...b262d2 )
by Yaroslav
09:39
created

ArgumentResolverTest::createArgumentMetadata()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
/*
4
 *
5
 * (c) Yaroslav Honcharuk <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Yarhon\RouteGuardBundle\Tests\Controller;
12
13
use PHPUnit\Framework\TestCase;
14
use Psr\Cache\CacheItemPoolInterface;
15
use Symfony\Component\Cache\Adapter\ArrayAdapter;
16
use Symfony\Component\HttpFoundation\RequestStack;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
19
use Symfony\Component\HttpFoundation\ParameterBag;
20
use Yarhon\RouteGuardBundle\Controller\ControllerMetadata;
21
use Yarhon\RouteGuardBundle\Controller\ArgumentResolver;
22
use Yarhon\RouteGuardBundle\Controller\ArgumentResolver\ArgumentValueResolverInterface;
23
use Yarhon\RouteGuardBundle\Controller\ArgumentResolver\ArgumentResolverContext;
24
use Yarhon\RouteGuardBundle\Routing\RequestAttributesFactory;
25
use Yarhon\RouteGuardBundle\Routing\RouteContext;
26
use Yarhon\RouteGuardBundle\Exception\RuntimeException;
27
28
/**
29
 * @author Yaroslav Honcharuk <[email protected]>
30
 */
31
class ArgumentResolverTest extends TestCase
32
{
33
    private $metadataCache;
34
35
    private $requestAttributesFactory;
36
37
    private $request;
38
39
    private $valueResolvers;
40
41
    private $resolver;
42
43
    public function setUp()
44
    {
45
        $this->metadataCache = new ArrayAdapter(0, false);
46
47
        $this->requestAttributesFactory = $this->createMock(RequestAttributesFactory::class);
48
49
        $this->request = $this->createMock(Request::class);
50
51
        $requestStack = $this->createMock(RequestStack::class);
52
53
        $requestStack->method('getCurrentRequest')
0 ignored issues
show
Bug introduced by
The method method() does not exist on PHPUnit\Framework\MockObject\MockObject. ( Ignorable by Annotation )

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

53
        $requestStack->/** @scrutinizer ignore-call */ 
54
                       method('getCurrentRequest')

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...
54
            ->willReturn($this->request);
55
56
        $this->valueResolvers = [
57
            $this->createMock(ArgumentValueResolverInterface::class),
58
            $this->createMock(ArgumentValueResolverInterface::class),
59
        ];
60
61
        $this->resolver = new ArgumentResolver($this->metadataCache, $this->requestAttributesFactory, $requestStack, $this->valueResolvers);
62
    }
63
64
    public function testGetArgument()
65
    {
66
        $routeContext = new RouteContext('index');
67
68
        $argumentMetadata = $this->createArgumentMetadata('arg1');
69
        $controllerMetadata = new ControllerMetadata('class::method', 'class', 'method', [$argumentMetadata]);
70
        $this->addMetadataCacheItem($routeContext->getName(), $controllerMetadata);
71
72
        $requestAttributes = new ParameterBag(['a' => 1]);
73
74
        $this->requestAttributesFactory->method('createAttributes')
75
            ->with($routeContext)
76
            ->willReturn($requestAttributes);
77
78
        $resolverContext = new ArgumentResolverContext($requestAttributes, $controllerMetadata->getName(), $this->request);
79
80
        $this->valueResolvers[0]->method('supports')
81
            ->willReturn(false);
82
83
        $this->valueResolvers[0]->expects($this->never())
84
            ->method('resolve');
85
86
        $this->valueResolvers[1]->method('supports')
87
            ->willReturn(true);
88
89
        $this->valueResolvers[1]->expects($this->once())
90
            ->method('resolve')
91
            ->with($resolverContext, $argumentMetadata)
92
            ->willReturn(5);
93
94
        $value = $this->resolver->getArgument($routeContext, 'arg1');
95
96
        $this->assertEquals(5, $value);
97
    }
98
99
    public function testGetArgumentNoControllerException()
100
    {
101
        $routeContext = new RouteContext('index');
102
103
        $this->addMetadataCacheItem($routeContext->getName(), null);
104
105
        $this->expectException(RuntimeException::class);
106
        $this->expectExceptionMessage('Route "index" does not have controller or controller name is unresolvable.');
107
108
        $this->resolver->getArgument($routeContext, 'arg1');
109
    }
110
111
    public function testGetArgumentNotExistingArgumentException()
112
    {
113
        $routeContext = new RouteContext('index');
114
115
        $this->addMetadataCacheItem($routeContext->getName(), new ControllerMetadata('class::method', 'class', 'method', []));
116
117
        $this->expectException(RuntimeException::class);
118
        $this->expectExceptionMessage('Route "index" controller "class::method" does not have argument "$arg1".');
119
120
        $this->resolver->getArgument($routeContext, 'arg1');
121
    }
122
123
    public function testGetArgumentNotResolvableArgumentException()
124
    {
125
        $routeContext = new RouteContext('index');
126
127
        $argumentMetadata = $this->createArgumentMetadata('arg1');
128
        $controllerMetadata = new ControllerMetadata('class::method', 'class', 'method', [$argumentMetadata]);
129
130
        $this->addMetadataCacheItem($routeContext->getName(), $controllerMetadata);
131
132
        $this->requestAttributesFactory->method('createAttributes')
133
            ->willReturn(new ParameterBag());
134
135
        $this->valueResolvers[0]->method('supports')
136
            ->willReturn(false);
137
138
        $this->valueResolvers[1]->method('supports')
139
            ->willReturn(false);
140
141
        $this->expectException(RuntimeException::class);
142
        $this->expectExceptionMessage('Route "index" controller "class::method" requires that you provide a value for the "$arg1" argument.');
143
144
        $this->resolver->getArgument($routeContext, 'arg1');
145
    }
146
147
    public function testGetArgumentNoMetadataException()
148
    {
149
        $routeContext = new RouteContext('index');
150
151
        $this->expectException(RuntimeException::class);
152
        $this->expectExceptionMessage('Cannot get ControllerMetadata for route "index".');
153
154
        $this->resolver->getArgument($routeContext, 'arg1');
155
    }
156
157
    public function testGetArgumentInternalCache()
158
    {
159
        $routeContext = new RouteContext('index');
160
161
        $controllerMetadata = new ControllerMetadata('class::method', 'class', 'method', [
162
            $this->createArgumentMetadata('arg1'),
163
            $this->createArgumentMetadata('arg2'),
164
        ]);
165
        $this->addMetadataCacheItem($routeContext->getName(), $controllerMetadata);
166
167
        $this->requestAttributesFactory->method('createAttributes')
168
            ->willReturn(new ParameterBag());
169
170
        $this->valueResolvers[0]->method('supports')
171
            ->willReturn(true);
172
173
        $resolvedValueOne = new \stdClass();
174
        $resolvedValueTwo = new \stdClass();
175
176
        $this->valueResolvers[0]->method('resolve')
177
            ->willReturnOnConsecutiveCalls($resolvedValueOne, $resolvedValueTwo);
178
179
        $this->valueResolvers[0]->expects($this->exactly(2))
180
            ->method('supports');
181
182
        $this->valueResolvers[0]->expects($this->exactly(2))
183
            ->method('resolve');
184
185
        $resolvedOne = $this->resolver->getArgument($routeContext, 'arg1');
186
        $resolvedTwo = $this->resolver->getArgument($routeContext, 'arg2');
187
        $resolvedThree = $this->resolver->getArgument($routeContext, 'arg1');
188
        $resolvedFour = $this->resolver->getArgument($routeContext, 'arg2');
189
190
        $this->assertSame($resolvedOne, $resolvedThree);
191
        $this->assertSame($resolvedTwo, $resolvedFour);
192
        $this->assertNotSame($resolvedOne, $resolvedTwo);
193
    }
194
195
    private function createArgumentMetadata($name)
196
    {
197
        return new ArgumentMetadata($name, 'int', false, false, null);
198
    }
199
200
    private function addMetadataCacheItem($name, $value)
201
    {
202
        $cacheItem = $this->metadataCache->getItem($name);
203
        $cacheItem->set($value);
204
        $this->metadataCache->save($cacheItem);
205
    }
206
}
207