Test Failed
Push — master ( 9c2fc7...64364c )
by Dan
07:49
created

Expectation::prepareInvocationNumeric()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Nopolabs\Test;
5
6
use Closure;
7
use Exception;
8
use PHPUnit\Framework\TestCase;
9
use PHPUnit_Framework_MockObject_Builder_InvocationMocker;
10
use PHPUnit_Framework_MockObject_Matcher_Invocation;
11
use PHPUnit_Framework_MockObject_MockObject;
12
13
class Expectation
14
{
15
    private $method;
16
    private $params;
17
    private $result;
18
    private $throws;
19
    private $invoked;
20
21
    public function __construct(
22
        string $method,
23
        array $params = [],
24
        $result = null,
25
        $throws = null,
26
        $invoked = null)
27
    {
28
        $this->method = $method;
29
        $this->params = $params;
30
        $this->result = $result;
31
        $this->throws = $throws;
32
        $this->invoked = $invoked;
33
    }
34
35
    public function getMethod() : string
36
    {
37
        return $this->method;
38
    }
39
40
    public function build(PHPUnit_Framework_MockObject_MockObject $mock) : void
41
    {
42
        $builder = $this->mockExpects($mock, $this->invoked);
43
44
        $this->mockMethod($builder, $this->method);
45
46
        if (!empty($this->params)) {
47
            $this->mockParams($builder, $this->params);
48
        }
49
50
        if ($this->result !== null) {
51
            $this->mockResult($builder, $this->params);
52
        }
53
54
        if ($this->throws !== null) {
55
            $this->mockThrows($builder, $this->throws);
56
        }
57
    }
58
59
    public function prepareInvocation($invoked) : PHPUnit_Framework_MockObject_Matcher_Invocation
60
    {
61
        if ($invoked === null) {
62
            return TestCase::any();
63
        }
64
65
        if (\is_object($invoked)) {
66
            return $invoked;
67
        }
68
69
        if (\is_numeric($invoked)) {
70
            return $this->prepareInvocationNumeric($invoked);
71
        }
72
73
        if (\is_string($invoked)) {
74
            return $this->prepareInvocationString($invoked);
75
        }
76
77
        throw new TestException("prepareInvocation cannot prepare '$invoked'");
78
    }
79
80
    protected function prepareInvocationNumeric(int $times): PHPUnit_Framework_MockObject_Matcher_Invocation
81
    {
82
        switch ($times) {
83
            case 0:
84
                return TestCase::never();
85
            case 1:
86
                return TestCase::once();
87
            default:
88
                return TestCase::exactly($times);
89
        }
90
    }
91
92
    protected function prepareInvocationString(string $invoked): PHPUnit_Framework_MockObject_Matcher_Invocation
93
    {
94
        if (preg_match("/(?'method'\w+)(?:\s+(?'count'\d+))?/", $invoked, $matches)) {
95
            $method = $matches['method'];
96
            if (!isset($matches['count'])) {
97
                switch ($method) {
98
                    case 'once':
99
                        return TestCase::once();
100
                    case 'any':
101
                        return TestCase::any();
102
                    case 'never':
103
                        return TestCase::never();
104
                    case 'atLeastOnce':
105
                        return TestCase::atLeastOnce();
106
                }
107
            } else {
108
                $count = (int)$matches['count'];
109
                switch ($method) {
110
                    case 'atLeast':
111
                        return TestCase::atLeast($count);
112
                    case 'exactly':
113
                        return TestCase::exactly($count);
114
                    case 'atMost':
115
                        return TestCase::atMost($count);
116
                }
117
            }
118
        }
119
120
        throw new TestException("prepareInvocationString cannot handle '$invoked'");
121
    }
122
123
    protected function mockExpects(
124
        PHPUnit_Framework_MockObject_MockObject $mock,
125
        $invoked) : PHPUnit_Framework_MockObject_Builder_InvocationMocker
126
    {
127
        return $mock->expects($this->prepareInvocation($invoked));
128
    }
129
130
    protected function mockMethod(
131
        PHPUnit_Framework_MockObject_Builder_InvocationMocker $builder,
132
        string $method) : PHPUnit_Framework_MockObject_Builder_InvocationMocker
133
    {
134
        return $builder->method($method);
135
    }
136
137
    protected function mockParams(
138
        PHPUnit_Framework_MockObject_Builder_InvocationMocker $builder,
139
        array $params) : PHPUnit_Framework_MockObject_Builder_InvocationMocker
140
    {
141
        return \call_user_func_array([$builder, 'with'], $params);
142
    }
143
144
    protected function mockResult(
145
        PHPUnit_Framework_MockObject_Builder_InvocationMocker $builder,
146
        $result) : PHPUnit_Framework_MockObject_Builder_InvocationMocker
147
    {
148
        if ($result instanceof Closure) {
149
            return $builder->willReturnCallback($result);
150
        }
151
152
        return $builder->willReturn($result);
153
    }
154
155
    protected function mockThrows(
156
        PHPUnit_Framework_MockObject_Builder_InvocationMocker $builder,
157
        $throws) : PHPUnit_Framework_MockObject_Builder_InvocationMocker
158
    {
159
        if (\is_string($throws)) {
160
            $throws = new Exception($throws);
161
        }
162
163
        return $builder->willThrowException($throws);
164
    }
165
}
166