Completed
Pull Request — master (#37)
by Angelo
03:16 queued 01:16
created

AbstractMockingStrategy   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 155
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 5
dl 0
loc 155
ccs 41
cts 41
cp 1
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A checkMockType() 0 14 2
A verifyMockType() 0 6 2
doDecorate() 0 1 ?
A get() 0 6 1
doGet() 0 1 ?
A getMockType() 0 6 1
A setMockType() 0 4 1
A checkDependencies() 0 12 2
A build() 0 14 2
doBuild() 0 1 ?
A decorate() 0 11 2
A call() 0 4 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\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 12
    final protected static function checkDependencies(string $dependencyClassName, string $dependencyPackageName)
31
    {
32 12
        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 string $fqcn
66
     * @return object
67
     */
68
    abstract protected function doBuild(string $fqcn);
69
70
    /**
71
     * @param object $mock
72
     * @param array $stubs
73
     * @return void
74
     */
75 89
    public function decorate($mock, array $stubs)
76
    {
77 89
        $this->checkMockType($mock);
78
79 89
        $stubs = StubFactory::fromArray($stubs);
80
81
        /** @var Stub $stub */
82 89
        foreach ($stubs as $stub) {
83 89
            $this->doDecorate($mock, $stub);
84
        }
85
    }
86
87
    /**
88
     * @param object $mock
89
     *
90
     * @throws NotImplementedException
91
     * @throws InvalidArgumentException
92
     */
93 89
    final protected function checkMockType($mock)
94
    {
95 89
        $this->verifyMockType();
96
97 89
        if (!is_a($mock, $this->mockType)) {
98 8
            throw new InvalidArgumentException(
99 8
                sprintf(
100 8
                    'Mock object must be of type "%s", "%s" given',
101 8
                    $this->mockType,
102 8
                    gettype($mock)
103
                )
104
            );
105
        }
106
    }
107
108
    /**
109
     * @return void
110
     *
111
     * @throws NotImplementedException
112
     */
113 90
    private function verifyMockType()
114
    {
115 90
        if (!$this->mockType) {
116 1
            throw new NotImplementedException('Mock type was not defined');
117
        }
118
    }
119
120
    /**
121
     * @param object $mock
122
     * @param Stub $stub
123
     * @return void
124
     */
125
    abstract protected function doDecorate($mock, Stub $stub);
126
127
    /**
128
     * @param object $mock
129
     * @return object
130
     *
131
     * @throws NotImplementedException
132
     * @throws InvalidArgumentException
133
     */
134 50
    public function get($mock)
135
    {
136 50
        $this->checkMockType($mock);
137
138 46
        return $this->doGet($mock);
139
    }
140
141
    /**
142
     * @param object $mock
143
     * @return object
144
     */
145
    abstract protected function doGet($mock);
146
147
    /**
148
     * @return string
149
     *
150
     * @throws NotImplementedException
151
     */
152 23
    public function getMockType(): string
153
    {
154 23
        $this->verifyMockType();
155
156 22
        return $this->mockType;
157
    }
158
159
    /**
160
     * @param string $fqcn
161
     */
162 11
    final protected function setMockType(string $fqcn)
163
    {
164 11
        $this->mockType = $fqcn;
165
    }
166
167 1
    public function call($object, string $name, array $arguments)
168
    {
169 1
        return $object->$name(...$arguments);
170
    }
171
}
172