Completed
Pull Request — master (#37)
by Alberto
03:13
created

AbstractMockingStrategy::verifyMockType()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 0
crap 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Moka\Strategy;
5
6
use Moka\Exception\InvalidArgumentException;
7
use Moka\Exception\MissingDependencyException;
8
use Moka\Exception\MockNotCreatedException;
9
use Moka\Exception\NotImplementedException;
10
use Moka\Factory\StubFactory;
11
use Moka\Stub\Stub;
12
13
/**
14
 * Class AbstractMockingStrategy
15
 * @package Moka\Strategy
16
 */
17
abstract class AbstractMockingStrategy implements MockingStrategyInterface
18
{
19
    /**
20
     * @var string
21
     */
22
    private $mockType;
23
24
    /**
25
     * @param string $dependencyClassName
26
     * @param string $dependencyPackageName
27
     *
28
     * @throws MissingDependencyException
29
     */
30 10
    final protected static function checkDependencies(string $dependencyClassName, string $dependencyPackageName)
31
    {
32 10
        if (!class_exists($dependencyClassName)) {
33 1
            throw new MissingDependencyException(
34 1
                sprintf(
35 1
                    'Class "%s" does not exist, please install package "%s"',
36 1
                    $dependencyClassName,
37 1
                    $dependencyPackageName
38
                )
39
            );
40
        }
41
    }
42
43
    /**
44
     * @param string $fqcn
45
     * @return object
46
     *
47
     * @throws MockNotCreatedException
48
     */
49 98
    public function build(string $fqcn)
50
    {
51
        try {
52 98
            return $this->doBuild($fqcn);
53 11
        } catch (\Throwable $exception) {
54 11
            throw new MockNotCreatedException(
55 11
                sprintf(
56 11
                    'Cannot create mock object for FQCN "%s": %s',
57 11
                    $fqcn,
58 11
                    $exception->getMessage()
59
                )
60
            );
61
        }
62
    }
63
64
    /**
65
     * @param object $mock
66
     * @param array $stubs
67
     * @return void
68
     *
69
     * @throws InvalidArgumentException
70
     * @throws NotImplementedException
71
     */
72 90
    public function decorate($mock, array $stubs)
73
    {
74 90
        $this->checkMockType($mock);
75
76 90
        $stubs = StubFactory::fromArray($stubs);
77
78
        /** @var Stub $stub */
79 90
        foreach ($stubs as $stub) {
80 90
            $this->doDecorate($mock, $stub);
81
        }
82
    }
83
84
    /**
85
     * @param object $mock
86
     * @return object
87
     *
88
     * @throws NotImplementedException
89
     * @throws InvalidArgumentException
90
     */
91 58
    public function get($mock)
92
    {
93 58
        $this->checkMockType($mock);
94
95 54
        return $this->doGet($mock);
96
    }
97
98
    /**
99
     * @param object $mock
100
     * @param string $methodName
101
     * @return mixed
102
     *
103
     * @throws NotImplementedException
104
     */
105 3
    public function call($mock, string $methodName)
106
    {
107 3
        $this->checkMockType($mock);
108
109 3
        return $this->doCall($mock, $methodName);
110
    }
111
112
    /**
113
     * @return string
114
     *
115
     * @throws NotImplementedException
116
     */
117 23
    public function getMockType(): string
118
    {
119 23
        $this->verifyMockType();
120
121 22
        return $this->mockType;
122
    }
123
124
    /**
125
     * @param string $fqcn
126
     */
127 10
    final protected function setMockType(string $fqcn)
128
    {
129 10
        $this->mockType = $fqcn;
130
    }
131
132
    /**
133
     * @param object $mock
134
     *
135
     * @throws NotImplementedException
136
     * @throws InvalidArgumentException
137
     */
138 99
    final protected function checkMockType($mock)
139
    {
140 99
        $this->verifyMockType();
141
142 99
        if (!is_a($mock, $this->mockType)) {
143 8
            throw new InvalidArgumentException(
144 8
                sprintf(
145 8
                    'Mock object must be of type "%s", "%s" given',
146 8
                    $this->mockType,
147 8
                    gettype($mock)
148
                )
149
            );
150
        }
151
    }
152
153
    /**
154
     * @return void
155
     *
156
     * @throws NotImplementedException
157
     */
158 100
    private function verifyMockType()
159
    {
160 100
        if (!$this->mockType) {
161 1
            throw new NotImplementedException('Mock type was not defined');
162
        }
163
    }
164
165
    /**
166
     * @param string $fqcn
167
     * @return object
168
     */
169
    abstract protected function doBuild(string $fqcn);
170
171
    /**
172
     * @param object $mock
173
     * @param Stub $stub
174
     * @return void
175
     */
176
    abstract protected function doDecorate($mock, Stub $stub);
177
178
    /**
179
     * @param object $mock
180
     * @return object
181
     */
182
    abstract protected function doGet($mock);
183
184
    /**
185
     * @param object $mock
186
     * @param string $methodName
187
     * @return mixed
188
     *
189
     * @throws \Error
190
     */
191 1
    protected function doCall($mock, string $methodName)
192
    {
193 1
        throw new \Error(
194 1
            sprintf(
1 ignored issue
show
Unused Code introduced by
The call to Error::__construct() has too many arguments starting with sprintf('Undefined prope...ss($this), $methodName).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
195 1
                'Undefined property: %s::$%s',
196 1
                get_class($this),
197 1
                $methodName
198
            )
199
        );
200
    }
201
}
202