Skip to content

Commit 609d52d

Browse files
Closes #4480
1 parent 0a0ac90 commit 609d52d

File tree

7 files changed

+187
-1
lines changed

7 files changed

+187
-1
lines changed

.php_cs.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ $finder = PhpCsFixer\Finder::create()
1919
->notName('*.phpt')
2020
->notName('ClassWithAllPossibleReturnTypes.php')
2121
->notName('ClassWithUnionReturnTypes.php')
22+
->notName('ClassWithStaticReturnTypes.php')
2223
->notName('ValueObjectWithEqualsMethodWithUnionReturnType.php')
2324
->notName('ValueObjectWithEqualsMethodThatHasUnionParameterType.php');
2425

ChangeLog-9.4.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
All notable changes of the PHPUnit 9.4 release series are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
44

5+
## [9.4.1] - 2020-MM-DD
6+
7+
### Fixed
8+
9+
* [#4480](https://github.com/sebastianbergmann/phpunit/issues/4480): Methods with "static" return type (introduced in PHP 8) are not handled correctly by test double code generator
10+
511
## [9.4.0] - 2020-10-02
612

713
### Added
@@ -14,4 +20,5 @@ All notable changes of the PHPUnit 9.4 release series are documented in this fil
1420

1521
* The PHPUnit XML configuration generator (that is invoked using the `--generate-configuration` CLI option) now asks for a cache directory (default: `.phpunit.cache`)
1622

23+
[9.4.1]: https://github.com/sebastianbergmann/phpunit/compare/9.4.0...9.4
1724
[9.4.0]: https://github.com/sebastianbergmann/phpunit/compare/9.3.11...9.4.0

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"sebastian/global-state": "^5.0.1",
4848
"sebastian/object-enumerator": "^4.0.3",
4949
"sebastian/resource-operations": "^3.0.3",
50-
"sebastian/type": "^2.2.2",
50+
"sebastian/type": "^2.3",
5151
"sebastian/version": "^3.0.2"
5252
},
5353
"require-dev": {

src/Framework/MockObject/Invocation.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111

1212
use function array_map;
1313
use function explode;
14+
use function get_class;
1415
use function implode;
1516
use function is_object;
1617
use function sprintf;
1718
use function strpos;
1819
use function strtolower;
1920
use function substr;
21+
use Doctrine\Instantiator\Instantiator;
2022
use PHPUnit\Framework\SelfDescribing;
2123
use PHPUnit\Util\Type;
2224
use SebastianBergmann\Exporter\Exporter;
@@ -151,6 +153,9 @@ public function generateReturnValue()
151153
case 'array':
152154
return [];
153155

156+
case 'static':
157+
return (new Instantiator)->instantiate(get_class($this->object));
158+
154159
case 'object':
155160
return new stdClass;
156161

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
namespace PHPUnit\TestFixture;
12+
13+
class ClassWithStaticReturnTypes
14+
{
15+
public function returnsStatic(): static
16+
{
17+
}
18+
19+
public function returnsStaticOrNull(): ?static
20+
{
21+
}
22+
23+
public function returnsUnionWithStatic(): static|\stdClass
24+
{
25+
}
26+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
--TEST--
2+
\PHPUnit\Framework\MockObject\Generator::generate('Foo', [], 'MockFoo', true, true)
3+
--SKIPIF--
4+
<?php declare(strict_types=1);
5+
if (PHP_MAJOR_VERSION < 8) {
6+
print 'skip: PHP 8 is required.';
7+
}
8+
--FILE--
9+
<?php declare(strict_types=1);
10+
class ClassWithStaticReturnTypes
11+
{
12+
public function returnsStatic(): static
13+
{
14+
}
15+
16+
public function returnsStaticOrNull(): ?static
17+
{
18+
}
19+
20+
public function returnsUnionWithStatic(): static|\stdClass
21+
{
22+
}
23+
}
24+
25+
require __DIR__ . '/../../../../vendor/autoload.php';
26+
27+
$generator = new \PHPUnit\Framework\MockObject\Generator;
28+
29+
$mock = $generator->generate(
30+
'ClassWithStaticReturnTypes',
31+
[],
32+
'MockClassWithStaticReturnTypes',
33+
true,
34+
true
35+
);
36+
37+
print $mock->getClassCode();
38+
--EXPECTF--
39+
declare(strict_types=1);
40+
41+
class MockClassWithStaticReturnTypes extends ClassWithStaticReturnTypes implements PHPUnit\Framework\MockObject\MockObject
42+
{
43+
use \PHPUnit\Framework\MockObject\Api;
44+
use \PHPUnit\Framework\MockObject\Method;
45+
use \PHPUnit\Framework\MockObject\MockedCloneMethod;
46+
47+
public function returnsStatic(): static
48+
{
49+
$__phpunit_arguments = [];
50+
$__phpunit_count = func_num_args();
51+
52+
if ($__phpunit_count > 0) {
53+
$__phpunit_arguments_tmp = func_get_args();
54+
55+
for ($__phpunit_i = 0; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
56+
$__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
57+
}
58+
}
59+
60+
$__phpunit_result = $this->__phpunit_getInvocationHandler()->invoke(
61+
new \PHPUnit\Framework\MockObject\Invocation(
62+
'ClassWithStaticReturnTypes', 'returnsStatic', $__phpunit_arguments, 'static', $this, true
63+
)
64+
);
65+
66+
return $__phpunit_result;
67+
}
68+
69+
public function returnsStaticOrNull(): ?static
70+
{
71+
$__phpunit_arguments = [];
72+
$__phpunit_count = func_num_args();
73+
74+
if ($__phpunit_count > 0) {
75+
$__phpunit_arguments_tmp = func_get_args();
76+
77+
for ($__phpunit_i = 0; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
78+
$__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
79+
}
80+
}
81+
82+
$__phpunit_result = $this->__phpunit_getInvocationHandler()->invoke(
83+
new \PHPUnit\Framework\MockObject\Invocation(
84+
'ClassWithStaticReturnTypes', 'returnsStaticOrNull', $__phpunit_arguments, '?static', $this, true
85+
)
86+
);
87+
88+
return $__phpunit_result;
89+
}
90+
91+
public function returnsUnionWithStatic(): static|stdClass
92+
{
93+
$__phpunit_arguments = [];
94+
$__phpunit_count = func_num_args();
95+
96+
if ($__phpunit_count > 0) {
97+
$__phpunit_arguments_tmp = func_get_args();
98+
99+
for ($__phpunit_i = 0; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
100+
$__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
101+
}
102+
}
103+
104+
$__phpunit_result = $this->__phpunit_getInvocationHandler()->invoke(
105+
new \PHPUnit\Framework\MockObject\Invocation(
106+
'ClassWithStaticReturnTypes', 'returnsUnionWithStatic', $__phpunit_arguments, 'static|stdClass', $this, true
107+
)
108+
);
109+
110+
return $__phpunit_result;
111+
}
112+
}

tests/unit/Framework/MockObject/MockObjectTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99
*/
1010
use PHPUnit\Framework\ExpectationFailedException;
1111
use PHPUnit\Framework\MockObject\MockObject;
12+
use PHPUnit\Framework\MockObject\Stub;
1213
use PHPUnit\Framework\TestCase;
1314
use PHPUnit\TestFixture\AbstractTrait;
1415
use PHPUnit\TestFixture\AnInterface;
1516
use PHPUnit\TestFixture\ClassThatImplementsSerializable;
1617
use PHPUnit\TestFixture\ClassWithAllPossibleReturnTypes;
1718
use PHPUnit\TestFixture\ClassWithSelfTypeHint;
1819
use PHPUnit\TestFixture\ClassWithStaticMethod;
20+
use PHPUnit\TestFixture\ClassWithStaticReturnTypes;
1921
use PHPUnit\TestFixture\ClassWithUnionReturnTypes;
2022
use PHPUnit\TestFixture\ExampleTrait;
2123
use PHPUnit\TestFixture\InterfaceWithStaticMethod;
@@ -1135,6 +1137,39 @@ public function testMixedReturnTypeIsDoubledCorrectly(): void
11351137
$this->assertNull($stub->returnsMixed());
11361138
}
11371139

1140+
/**
1141+
* @requires PHP > 8.0
1142+
*/
1143+
public function testStaticReturnTypeIsDoubledCorrectly(): void
1144+
{
1145+
/** @var ClassWithStaticReturnTypes|Stub $stub */
1146+
$stub = $this->createStub(ClassWithStaticReturnTypes::class);
1147+
1148+
$this->assertInstanceOf(ClassWithStaticReturnTypes::class, $stub->returnsStatic());
1149+
}
1150+
1151+
/**
1152+
* @requires PHP > 8.0
1153+
*/
1154+
public function testUnionReturnTypeWithStaticIsDoubledCorrectly(): void
1155+
{
1156+
/** @var ClassWithStaticReturnTypes|Stub $stub */
1157+
$stub = $this->createStub(ClassWithStaticReturnTypes::class);
1158+
1159+
$this->assertInstanceOf(ClassWithStaticReturnTypes::class, $stub->returnsUnionWithStatic());
1160+
}
1161+
1162+
/**
1163+
* @requires PHP > 8.0
1164+
*/
1165+
public function testNullableStaticReturnTypeIsDoubledCorrectly(): void
1166+
{
1167+
/** @var ClassWithStaticReturnTypes|Stub $stub */
1168+
$stub = $this->createStub(ClassWithStaticReturnTypes::class);
1169+
1170+
$this->assertNull($stub->returnsStaticOrNull());
1171+
}
1172+
11381173
public function testTraitCanBeDoubled(): void
11391174
{
11401175
$object = $this->getObjectForTrait(ExampleTrait::class);

0 commit comments

Comments
 (0)