These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | declare(strict_types=1); |
||
3 | |||
4 | namespace Moka\Tests; |
||
5 | |||
6 | use Moka\Exception\InvalidArgumentException; |
||
7 | use Moka\Factory\StubFactory; |
||
8 | use Moka\Strategy\MockingStrategyInterface; |
||
9 | use Moka\Stub\StubSet; |
||
10 | use PHPUnit\Framework\TestCase; |
||
11 | use Tests\AbstractTestClass; |
||
12 | use Tests\BarTestClass; |
||
13 | use Tests\FooTestClass; |
||
14 | use Tests\TestInterface; |
||
15 | |||
16 | abstract class MokaMockingStrategyTestCase extends TestCase |
||
17 | { |
||
18 | /** |
||
19 | * @var MockingStrategyInterface |
||
20 | */ |
||
21 | protected $strategy; |
||
22 | |||
23 | /** |
||
24 | * @var object |
||
25 | */ |
||
26 | protected $mock; |
||
27 | |||
28 | /** |
||
29 | * @var StubSet |
||
30 | */ |
||
31 | protected $stubs; |
||
32 | |||
33 | /** |
||
34 | * @var string |
||
35 | */ |
||
36 | private $className; |
||
37 | |||
38 | /** |
||
39 | * @var array |
||
40 | */ |
||
41 | private $methodsWithValues = []; |
||
42 | |||
43 | private $methodName; |
||
44 | |||
45 | final public function testGetMockTypeSuccess() |
||
46 | { |
||
47 | $this->assertInternalType('string', $this->strategy->getMockType()); |
||
48 | } |
||
49 | |||
50 | final public function testBuildClassSuccess() |
||
51 | { |
||
52 | $this->assertInstanceOf($this->strategy->getMockType(), $this->mock); |
||
53 | } |
||
54 | |||
55 | final public function testBuildInterfaceSuccess() |
||
56 | { |
||
57 | $mock = $this->strategy->build(TestInterface::class); |
||
58 | |||
59 | $this->assertInstanceOf($this->strategy->getMockType(), $mock); |
||
60 | } |
||
61 | |||
62 | final public function testBuildAbstractClassSuccess() |
||
63 | { |
||
64 | $mock = $this->strategy->build(AbstractTestClass::class); |
||
65 | |||
66 | $this->assertInstanceOf($this->strategy->getMockType(), $mock); |
||
67 | } |
||
68 | |||
69 | final public function testDecorateFailure() |
||
70 | { |
||
71 | $this->expectException(InvalidArgumentException::class); |
||
72 | |||
73 | $this->strategy->decorate(new \stdClass(), $this->stubs); |
||
74 | } |
||
75 | |||
76 | final public function testDecorateWrongTypeHintFailure() |
||
77 | { |
||
78 | $this->strategy->decorate($this->mock, StubFactory::fromArray([ |
||
0 ignored issues
–
show
|
|||
79 | 'getSelf' => mt_rand() |
||
80 | ])); |
||
81 | |||
82 | $this->expectException(\TypeError::class); |
||
83 | $this->strategy->get($this->mock)->getSelf(); |
||
84 | } |
||
85 | |||
86 | final public function testDecorateSingleCallSuccess() |
||
87 | { |
||
88 | $this->assertSame($this->methodsWithValues['isTrue'], $this->strategy->get($this->mock)->isTrue()); |
||
89 | |||
90 | $this->expectException(\Exception::class); |
||
91 | $this->expectExceptionMessage($this->methodsWithValues['throwException']->getMessage()); |
||
92 | $this->strategy->get($this->mock)->throwException(); |
||
93 | } |
||
94 | |||
95 | final public function testDecorateMultipleCallsSuccess() |
||
96 | { |
||
97 | $this->assertSame($this->methodsWithValues['getInt'], $this->strategy->get($this->mock)->getInt()); |
||
98 | $this->assertSame($this->methodsWithValues['getInt'], $this->strategy->get($this->mock)->getInt()); |
||
99 | } |
||
100 | |||
101 | final public function testDecorateOverriddenCallsFailure() |
||
102 | { |
||
103 | $this->strategy->decorate($this->mock, StubFactory::fromArray([ |
||
0 ignored issues
–
show
It seems like
\Moka\Factory\StubFactor...ception' => mt_rand())) targeting Moka\Factory\StubFactory::fromArray() can also be of type array<integer,object<Moka\Stub\Stub>> ; however, Moka\Strategy\MockingStrategyInterface::decorate() does only seem to accept object<Moka\Stub\StubSet> , maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
104 | 'getInt' => mt_rand(), |
||
105 | 'throwException' => mt_rand() |
||
106 | ])); |
||
107 | |||
108 | $this->assertSame($this->methodsWithValues['getInt'], $this->strategy->get($this->mock)->getInt()); |
||
109 | $this->assertSame($this->methodsWithValues['getInt'], $this->strategy->get($this->mock)->getInt()); |
||
110 | |||
111 | $this->expectException(\Exception::class); |
||
112 | $this->expectExceptionMessage($this->methodsWithValues['throwException']->getMessage()); |
||
113 | $this->strategy->get($this->mock)->throwException(); |
||
114 | } |
||
115 | |||
116 | final public function testDecorateCallWithArgumentSuccess() |
||
117 | { |
||
118 | $this->assertSame($this->methodsWithValues['withArgument'], $this->strategy->get($this->mock)->withArgument(mt_rand())); |
||
119 | } |
||
120 | |||
121 | final public function testDecorateCallWithMissingArgumentFailure() |
||
122 | { |
||
123 | $this->expectException(\Error::class); |
||
124 | |||
125 | $this->strategy->get($this->mock)->withArgument(); |
||
126 | } |
||
127 | |||
128 | final public function testDecorateCallWithWrongArgumentFailure() |
||
129 | { |
||
130 | $this->expectException(\TypeError::class); |
||
131 | |||
132 | $this->strategy->get($this->mock)->withArgument('string'); |
||
133 | } |
||
134 | |||
135 | final public function testGetSuccess() |
||
136 | { |
||
137 | $this->assertInstanceOf($this->className, $this->strategy->get($this->mock)); |
||
138 | } |
||
139 | |||
140 | final public function testGetFailure() |
||
141 | { |
||
142 | $this->expectException(InvalidArgumentException::class); |
||
143 | |||
144 | $this->strategy->get(new \stdClass()); |
||
145 | } |
||
146 | |||
147 | public function testMethodForward() |
||
148 | { |
||
149 | if (!$this->methodName) { |
||
150 | return; |
||
151 | } |
||
152 | |||
153 | try { |
||
154 | $this->strategy->build(\stdClass::class)->{$this->methodName}(); |
||
155 | $this->assertTrue(true); |
||
156 | } catch (\Error $e) { |
||
157 | $this->assertEquals(0, preg_match('/^Call to undefined method/', $e->getMessage())); |
||
158 | } |
||
159 | } |
||
160 | |||
161 | protected function setUp() |
||
162 | { |
||
163 | $this->className = [ |
||
164 | FooTestClass::class, |
||
165 | BarTestClass::class |
||
166 | ][random_int(0, 1)]; |
||
167 | |||
168 | $this->methodsWithValues = [ |
||
169 | 'isTrue' => !!random_int(0, 1), |
||
170 | 'getInt' => mt_rand(), |
||
171 | 'withArgument' => mt_rand(), |
||
172 | 'throwException' => new \Exception('' . mt_rand()) |
||
173 | ]; |
||
174 | |||
175 | $this->mock = $this->strategy->build($this->className); |
||
176 | |||
177 | // Mocking a StubSet is way too difficult. |
||
178 | $this->stubs = StubFactory::fromArray($this->methodsWithValues); |
||
179 | |||
180 | $this->strategy->decorate($this->mock, $this->stubs); |
||
181 | } |
||
182 | |||
183 | final protected function setStrategy(MockingStrategyInterface $strategy) |
||
184 | { |
||
185 | $this->strategy = $strategy; |
||
186 | } |
||
187 | |||
188 | final protected function setMethodName(string $methodName) |
||
189 | { |
||
190 | $this->methodName = $methodName; |
||
191 | } |
||
192 | |||
193 | final protected function getRandomFQCN() |
||
194 | { |
||
195 | return 'foo_' . rand(); |
||
196 | } |
||
197 | } |
||
198 |
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.