-
Notifications
You must be signed in to change notification settings - Fork 461
/
Php81LanguageFeaturesTest.php
241 lines (199 loc) · 5.25 KB
/
Php81LanguageFeaturesTest.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
<?php
namespace Mockery\Tests\PHP81;
use DateTime;
use Mockery;
use Mockery\Adapter\Phpunit\MockeryTestCase;
use PDO;
use ReturnTypeWillChange;
use RuntimeException;
use Serializable;
use function pcntl_fork;
use function pcntl_waitpid;
use function pcntl_wexitstatus;
/**
* @requires PHP 8.1.0-dev
*/
class Php81LanguageFeaturesTest extends MockeryTestCase
{
/**
* @test
* @group issue/339
*/
public function canMockClassesThatImplementSerializable()
{
$mock = mock(ClassThatImplementsSerializable::class);
$this->assertInstanceOf("Serializable", $mock);
}
/** @test */
public function it_can_mock_an_internal_class_with_tentative_return_types()
{
$mock = spy(DateTime::class);
$this->assertSame(0, $mock->getTimestamp());
}
/**
* @test
*/
public function it_can_mock_an_internal_class_with_tentative_union_return_types()
{
$mock = Mockery::mock(PDO::class);
$this->assertInstanceOf(PDO::class, $mock);
$mock->shouldReceive('exec')->once();
try {
$this->assertSame(0, $mock->exec('select * from foo.bar'));
} finally {
Mockery::close();
}
}
/** @test */
public function it_can_mock_a_class_with_return_type_will_change_attribute_and_no_return_type()
{
$mock = spy(ReturnTypeWillChangeAttributeNoReturnType::class);
$this->assertNull($mock->getTimestamp());
}
/** @test */
public function it_can_mock_a_class_with_return_type_will_change_attribute_and_wrong_return_type()
{
$mock = spy(ReturnTypeWillChangeAttributeWrongReturnType::class);
$this->assertSame(0.0, $mock->getTimestamp());
}
/** @test */
public function testMockingClassWithNewInInitializer()
{
$mock = Mockery::mock(ClassWithNewInInitializer::class);
$this->assertInstanceOf(ClassWithNewInInitializer::class, $mock);
}
/** @test */
public function it_can_mock_a_class_with_an_intersection_argument_type_hint()
{
$mock = Mockery::spy(ArgumentIntersectionTypeHint::class);
$object = new IntersectionTypeHelperClass();
$mock->allows()->foo($object);
$mock->foo($object);
$this->expectException(\TypeError::class);
$mock->foo(Mockery::mock(IntersectionTypeHelper1Interface::class));
}
/** @test */
public function it_can_mock_a_class_with_a_never_returning_type_hint()
{
$mock = Mockery::mock(NeverReturningTypehintClass::class)->makePartial();
$this->expectException(RuntimeException::class);
$mock->throws();
}
/**
* @requires extension pcntl
* @test
*/
public function it_can_mock_a_class_with_a_never_returning_type_hint_with_exit()
{
$mock = Mockery::mock(NeverReturningTypehintClass::class)->makePartial();
$pid = pcntl_fork();
if (-1 === $pid) {
$this->markTestSkipped("Couldn't fork for exit test");
return;
} elseif ($pid) {
pcntl_waitpid($pid, $status);
$this->assertEquals(123, pcntl_wexitstatus($status));
return;
}
$mock->exits();
}
/** @test */
public function it_can_parse_enum_as_default_value_correctly()
{
$mock = Mockery::mock(UsesEnums::class);
$mock->shouldReceive('set')->once();
$mock->set();
$this->assertEquals(SimpleEnum::first, $mock->enum); // check that mock did not set internal variable
}
}
interface LoggerInterface
{
}
class NullLogger implements LoggerInterface
{
}
class ClassWithNewInInitializer
{
public function __construct(
private Logger $logger = new NullLogger(),
) {
}
}
class ClassThatImplementsSerializable implements Serializable
{
public function serialize(): ?string
{
}
public function __serialize(): array
{
}
public function unserialize(string $data): void
{
}
public function __unserialize(array $data): void
{
}
}
class ReturnTypeWillChangeAttributeNoReturnType extends DateTime
{
#[ReturnTypeWillChange]
public function getTimestamp()
{
}
}
class ReturnTypeWillChangeAttributeWrongReturnType extends DateTime
{
#[ReturnTypeWillChange]
public function getTimestamp(): float
{
}
}
class NeverReturningTypehintClass
{
public function throws(): never
{
throw new RuntimeException('Never!');
}
public function exits(): never
{
exit(123);
}
}
class IntersectionTypeHelperClass implements IntersectionTypeHelper1Interface, IntersectionTypeHelper2Interface
{
public function foo(): int
{
return 123;
}
public function bar(): int
{
return 123;
}
}
interface IntersectionTypeHelper2Interface
{
public function foo(): int;
}
interface IntersectionTypeHelper1Interface
{
public function bar(): int;
}
class ArgumentIntersectionTypeHint
{
public function foo(IntersectionTypeHelper1Interface&IntersectionTypeHelper2Interface $foo)
{
}
}
enum SimpleEnum
{
case first;
case second;
}
class UsesEnums
{
public SimpleEnum $enum = SimpleEnum::first;
public function set(SimpleEnum $enum = SimpleEnum::second)
{
$this->enum = $enum;
}
}