Completed
Pull Request — master (#37)
by Alberto
01:52
created

AbstractMockingStrategy::call()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 3
dl 0
loc 6
ccs 3
cts 3
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
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 97
    public function build(string $fqcn)
50
    {
51
        try {
52 97
            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 91
    public function decorate($mock, array $stubs)
73
    {
74 91
        $this->checkMockType($mock);
75
76 91
        $stubs = StubFactory::fromArray($stubs);
77
78
        /** @var Stub $stub */
79 91
        foreach ($stubs as $stub) {
80 91
            $this->doDecorate($mock, $stub);
81
        }
82
    }
83
84
    /**
85
     * @param object $mock
86
     * @return object
87
     *
88
     * @throws NotImplementedException
89
     * @throws InvalidArgumentException
90
     */
91 56
    public function get($mock)
92
    {
93 56
        $this->checkMockType($mock);
94
95 52
        return $this->doGet($mock);
96
    }
97
98
    /**
99
     * @param object $mock
100
     * @param string $name
101
     * @param array $arguments
102
     * @return mixed
103
     */
104 2
    public function call($mock, string $name, array $arguments)
105
    {
106 2
        $this->checkMockType($mock);
107
108 2
        return $this->doCall($mock, $name, $arguments);
109
    }
110
111
    /**
112
     * @return string
113
     *
114
     * @throws NotImplementedException
115
     */
116 23
    public function getMockType(): string
117
    {
118 23
        $this->verifyMockType();
119
120 22
        return $this->mockType;
121
    }
122
123
    /**
124
     * @param string $fqcn
125
     */
126 9
    final protected function setMockType(string $fqcn)
127
    {
128 9
        $this->mockType = $fqcn;
129
    }
130
131
    /**
132
     * @param object $mock
133
     *
134
     * @throws NotImplementedException
135
     * @throws InvalidArgumentException
136
     */
137 97
    final protected function checkMockType($mock)
138
    {
139 97
        $this->verifyMockType();
140
141 97
        if (!is_a($mock, $this->mockType)) {
142 8
            throw new InvalidArgumentException(
143 8
                sprintf(
144 8
                    'Mock object must be of type "%s", "%s" given',
145 8
                    $this->mockType,
146 8
                    gettype($mock)
147
                )
148
            );
149
        }
150
    }
151
152
    /**
153
     * @return void
154
     *
155
     * @throws NotImplementedException
156
     */
157 98
    private function verifyMockType()
158
    {
159 98
        if (!$this->mockType) {
160 1
            throw new NotImplementedException('Mock type was not defined');
161
        }
162
    }
163
164
    /**
165
     * @param string $fqcn
166
     * @return object
167
     */
168
    abstract protected function doBuild(string $fqcn);
169
170
    /**
171
     * @param object $mock
172
     * @param Stub $stub
173
     * @return void
174
     */
175
    abstract protected function doDecorate($mock, Stub $stub);
176
177
    /**
178
     * @param object $mock
179
     * @return object
180
     */
181
    abstract protected function doGet($mock);
182
183
    /**
184
     * @param object $target
185
     * @param string $name
186
     * @param array $arguments
187
     * @return mixed
188
     */
189 2
    protected function doCall($target, string $name, array $arguments)
190
    {
191 2
        return $target->$name(...$arguments);
192
    }
193
}
194