Completed
Push — develop ( 8eb671...133594 )
by Mike
19:30 queued 09:24
created

Builder/Reflector/FunctionAssemblerTest.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * phpDocumentor
4
 *
5
 * PHP Version 5.3
6
 *
7
 * @author    Mike van Riel <[email protected]>
8
 * @author    Sven Hagemann <[email protected]>
9
 * @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com)
10
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
11
 * @link      http://phpdoc.org
12
 */
13
14
namespace phpDocumentor\Descriptor\Builder\Reflector;
15
16
use Mockery as m;
17
use phpDocumentor\Descriptor\ArgumentDescriptor;
18
use phpDocumentor\Descriptor\PackageDescriptor;
19
use phpDocumentor\Descriptor\ProjectDescriptorBuilder;
20
use phpDocumentor\Reflection\DocBlock;
21
use phpDocumentor\Reflection\Fqsen;
22
use phpDocumentor\Reflection\Php\Argument;
23
use phpDocumentor\Reflection\Php\Function_;
24
use phpDocumentor\Reflection\Types\Mixed_;
25
26
class FunctionAssemblerTest extends \Mockery\Adapter\Phpunit\MockeryTestCase
27
{
28
    /** @var FunctionAssembler $fixture */
29
    protected $fixture;
30
31
    /** @var ArgumentAssembler|m\MockInterface */
32
    protected $argumentAssemblerMock;
33
34
    /** @var ProjectDescriptorBuilder|m\MockInterface */
35
    protected $builderMock;
36
37
    /**
38
     * Creates a new fixture to test with.
39
     */
40
    protected function setUp()
41
    {
42
        $this->builderMock = m::mock('phpDocumentor\Descriptor\ProjectDescriptorBuilder');
43
        $this->builderMock->shouldReceive('buildDescriptor')->andReturnUsing(
44
            function ($value) {
45
                switch (get_class($value)) {
46
                    case DocBlock\Tags\Generic::class && $value->getName() === 'package':
47
                        return new PackageDescriptor();
48
                    default:
49
                        throw new \InvalidArgumentException('didn\'t expect ' . get_class($value));
50
                }
51
            }
52
        );
53
        $this->argumentAssemblerMock = m::mock('phpDocumentor\Descriptor\Builder\Reflector\ArgumentAssembler');
54
        $this->argumentAssemblerMock->shouldReceive('getBuilder')->andReturnNull();
55
        $this->argumentAssemblerMock->shouldReceive('setBuilder')->with($this->builderMock);
56
        $this->fixture = new FunctionAssembler($this->argumentAssemblerMock);
57
        $this->fixture->setBuilder($this->builderMock);
58
    }
59
60
    /**
61
     * @covers \phpDocumentor\Descriptor\Builder\Reflector\FunctionAssembler::__construct
62
     * @covers \phpDocumentor\Descriptor\Builder\Reflector\FunctionAssembler::create
63
     * @covers \phpDocumentor\Descriptor\Builder\Reflector\FunctionAssembler::mapReflectorPropertiesOntoDescriptor
64
     * @covers \phpDocumentor\Descriptor\Builder\Reflector\FunctionAssembler::addArgumentsToFunctionDescriptor
65
     * @covers \phpDocumentor\Descriptor\Builder\Reflector\FunctionAssembler::createArgumentDescriptor
66
     * @covers \phpDocumentor\Descriptor\Builder\Reflector\FunctionAssembler::addArgumentDescriptorToFunction
67
     */
68
    public function testCreateFunctionDescriptorFromReflector()
69
    {
70
        // Arrange
71
        $namespace = 'Namespace';
72
        $functionName = 'goodbyeWorld';
73
        $argumentName = 'waveHand';
74
75
        $argument = $this->givenAnArgumentWithName($argumentName);
76
        $functionReflectorMock = $this->givenAFunctionReflector(
77
            $namespace,
78
            $functionName,
79
            $argument,
80
            $this->givenADocBlockObject()
81
        );
82
        $argumentDescriptor = new ArgumentDescriptor();
83
        $argumentDescriptor->setName($argumentName);
84
85
        $this->argumentAssemblerMock->shouldReceive('create')->andReturn($argumentDescriptor);
0 ignored issues
show
The method shouldReceive does only exist in Mockery\MockInterface, but not in phpDocumentor\Descriptor...ector\ArgumentAssembler.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
86
87
        // Act
88
        $descriptor = $this->fixture->create($functionReflectorMock);
89
90
        // Assert
91
        $expectedFqsen = '\\' . $namespace . '\\' . $functionName . '()';
92
        $this->assertSame($expectedFqsen, (string) $descriptor->getFullyQualifiedStructuralElementName());
93
        $this->assertSame($functionName, $descriptor->getName());
94
        $this->assertSame('\\' . $namespace, $descriptor->getNamespace());
95
96
        $argument = $descriptor->getArguments()->get($argumentName);
97
        $this->assertSame($argumentDescriptor, $argument);
98
    }
99
100
    /**
101
     * Creates a sample function reflector for the tests with the given data.
102
     *
103
     * @param string $namespace
104
     * @param string $functionName
105
     * @param Argument $argumentMock
106
     * @param DocBlock|m\MockInterface $docBlockMock
107
     *
108
     * @return Function_
109
     */
110
    protected function givenAFunctionReflector($namespace, $functionName, $argumentMock, $docBlockMock)
111
    {
112
        $functionReflectorMock = new Function_(
113
            new Fqsen('\\' . $namespace . '\\' . $functionName . '()'),
114
            $docBlockMock
115
        );
116
117
        $functionReflectorMock->addArgument($argumentMock);
118
119
        return $functionReflectorMock;
120
    }
121
122
    /**
123
     * Generates a DocBlock object with applicable defaults for these tests.
124
     *
125
     * @return DocBlock
126
     */
127
    protected function givenADocBlockObject()
128
    {
129
        $docBlockDescription = new DocBlock\Description('This is an example description');
130
        return new DocBlock(
131
            'This is a example description',
132
            $docBlockDescription,
133
            [
134
                new DocBlock\Tags\Generic('package', new DocBlock\Description('PackageName')),
135
            ]
136
        );
137
    }
138
139
    /**
140
     * Prepares a mock Argument with the given name.
141
     *
142
     * @param string $argumentName
143
     *
144
     * @return Argument
145
     */
146
    protected function givenAnArgumentWithName($argumentName)
147
    {
148
        return new Argument($argumentName);
149
    }
150
}
151