Completed
Push — master ( 690881...d15d9f )
by Alberto
43s
created

AbstractMockingStrategy   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 200
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 200
ccs 53
cts 53
cp 1
rs 10
c 0
b 0
f 0
wmc 18
lcom 1
cbo 6

14 Methods

Rating   Name   Duplication   Size   Complexity  
A checkDependencies() 0 12 2
A build() 0 14 2
A decorate() 0 16 4
A get() 0 6 1
A call() 0 6 1
A getMockType() 0 6 1
A setMockType() 0 4 1
A checkMockType() 0 14 2
A verifyMockType() 0 6 2
doBuild() 0 1 ?
A doDecorateWithProperty() 0 4 1
doDecorateWithMethod() 0 1 ?
doGet() 0 1 ?
A doCall() 0 10 1
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\MethodStub;
12
use Moka\Stub\PropertyStub;
13
use Moka\Stub\StubInterface;
14
15
/**
16
 * Class AbstractMockingStrategy
17
 * @package Moka\Strategy
18
 */
19
abstract class AbstractMockingStrategy implements MockingStrategyInterface
20
{
21
    /**
22
     * @var string
23
     */
24
    private $mockType;
25
26
    /**
27
     * @param string $dependencyClassName
28
     * @param string $dependencyPackageName
29
     *
30
     * @throws MissingDependencyException
31
     */
32 10
    final protected static function checkDependencies(string $dependencyClassName, string $dependencyPackageName)
33
    {
34 10
        if (!class_exists($dependencyClassName)) {
35 1
            throw new MissingDependencyException(
36 1
                sprintf(
37 1
                    'Class "%s" does not exist, please install package "%s"',
38 1
                    $dependencyClassName,
39 1
                    $dependencyPackageName
40
                )
41
            );
42
        }
43
    }
44
45
    /**
46
     * @param string $fqcn
47
     * @return object
48
     *
49
     * @throws MockNotCreatedException
50
     */
51 85
    public function build(string $fqcn)
52
    {
53
        try {
54 85
            return $this->doBuild($fqcn);
55 1
        } catch (\Throwable $exception) {
56 1
            throw new MockNotCreatedException(
57 1
                sprintf(
58 1
                    'Cannot create mock object for FQCN "%s": %s',
59 1
                    $fqcn,
60 1
                    $exception->getMessage()
61
                )
62
            );
63
        }
64
    }
65
66
    /**
67
     * @param object $mock
68
     * @param StubInterface[] $stubs
69
     * @return void
70
     *
71
     * @throws InvalidArgumentException
72
     * @throws NotImplementedException
73
     */
74 76
    public function decorate($mock, array $stubs)
75
    {
76 76
        $this->checkMockType($mock);
77
78 76
        $stubs = StubFactory::fromArray($stubs);
79
80 76
        foreach ($stubs as $stub) {
81 76
            if ($stub instanceof PropertyStub) {
82 76
                $this->doDecorateWithProperty($mock, $stub);
83
            }
84
85 76
            if ($stub instanceof MethodStub) {
86 76
                $this->doDecorateWithMethod($mock, $stub);
87
            }
88
        }
89
    }
90
91
    /**
92
     * @param object $mock
93
     * @return object
94
     *
95
     * @throws NotImplementedException
96
     * @throws InvalidArgumentException
97
     */
98 71
    public function get($mock)
99
    {
100 71
        $this->checkMockType($mock);
101
102 67
        return $this->doGet($mock);
103
    }
104
105
    /**
106
     * @param object $mock
107
     * @param string $methodName
108
     * @return mixed
109
     *
110
     * @throws NotImplementedException
111
     */
112 3
    public function call($mock, string $methodName)
113
    {
114 3
        $this->checkMockType($mock);
115
116 3
        return $this->doCall($mock, $methodName);
117
    }
118
119
    /**
120
     * @return string
121
     *
122
     * @throws NotImplementedException
123
     */
124 21
    public function getMockType(): string
125
    {
126 21
        $this->verifyMockType();
127
128 20
        return $this->mockType;
129
    }
130
131
    /**
132
     * @param string $fqcn
133
     */
134 11
    final protected function setMockType(string $fqcn)
135
    {
136 11
        $this->mockType = $fqcn;
137
    }
138
139
    /**
140
     * @param object $mock
141
     *
142
     * @throws NotImplementedException
143
     * @throws InvalidArgumentException
144
     */
145 85
    final protected function checkMockType($mock)
146
    {
147 85
        $this->verifyMockType();
148
149 85
        if (!is_a($mock, $this->mockType)) {
150 8
            throw new InvalidArgumentException(
151 8
                sprintf(
152 8
                    'Mock object must be an instance of "%s", "%s" given',
153 8
                    $this->mockType,
154 8
                    gettype($mock)
155
                )
156
            );
157
        }
158
    }
159
160
    /**
161
     * @return void
162
     *
163
     * @throws NotImplementedException
164
     */
165 86
    private function verifyMockType()
166
    {
167 86
        if (!$this->mockType) {
168 1
            throw new NotImplementedException('Mock type was not defined');
169
        }
170
    }
171
172
    /**
173
     * @param string $fqcn
174
     * @return object
175
     */
176
    abstract protected function doBuild(string $fqcn);
177
178
    /**
179
     * @param object $mock
180
     * @param PropertyStub $stub
181
     * @return void
182
     */
183 76
    protected function doDecorateWithProperty($mock, PropertyStub $stub)
184
    {
185 76
        $mock->{$stub->getName()} = $stub->getValue();
186
    }
187
188
    /**
189
     * @param object $mock
190
     * @param MethodStub $stub
191
     * @return void
192
     */
193
    abstract protected function doDecorateWithMethod($mock, MethodStub $stub);
194
195
    /**
196
     * @param object $mock
197
     * @return object
198
     */
199
    abstract protected function doGet($mock);
200
201
    /**
202
     * @param object $mock
203
     * @param string $methodName
204
     * @return mixed
205
     *
206
     * @throws \Error
207
     */
208 1
    protected function doCall($mock, string $methodName)
209
    {
210 1
        throw new \Error(
211 1
            sprintf(
212 1
                'Undefined property: %s::$%s',
213 1
                get_class($this),
214 1
                $methodName
215
            )
216
        );
217
    }
218
}
219