Skip to content

Commit e5831e5

Browse files
author
Heiko Jerichen
committed
Set support for PHPUnit versions of "^9.6.21 | ^10.0 | ^11.0"
1 parent d106a3e commit e5831e5

File tree

8 files changed

+98
-52
lines changed

8 files changed

+98
-52
lines changed

.idea/codeStyles/Project.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"require": {
1313
"php": "^8.2",
1414
"phpspec/prophecy": "^1.8",
15-
"phpunit/php-text-template": "^2.0"
15+
"phpunit/php-text-template": "^2.0 | ^3.0 | ^4.0"
1616
},
1717
"autoload": {
1818
"psr-4": {
@@ -22,7 +22,7 @@
2222
},
2323
"require-dev": {
2424
"roave/security-advisories": "dev-latest",
25-
"phpunit/phpunit": "^9.0",
25+
"phpunit/phpunit": "^9.6.21 | ^10.0 | ^11.0",
2626
"phpspec/prophecy-phpunit": "^2.0"
2727
}
2828
}

phpunit.bootstrap.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
error_reporting(E_ALL);

phpunit.xml.dist

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2-
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
2+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.5/phpunit.xsd"
33
cacheResult="false"
4-
bootstrap="./vendor/autoload.php">
4+
bootstrap="./vendor/autoload.php"
5+
displayDetailsOnTestsThatTriggerDeprecations="true"
6+
displayDetailsOnTestsThatTriggerErrors="true"
7+
displayDetailsOnTestsThatTriggerNotices="true"
8+
displayDetailsOnTestsThatTriggerWarnings="true"
9+
displayDetailsOnPhpunitDeprecations="true">
510
<testsuites>
611
<testsuite name="Test Suite">
712
<directory>./tests</directory>
813
</testsuite>
914
</testsuites>
10-
<coverage>
15+
<source>
1116
<include>
12-
<directory suffix=".php">./src</directory>
17+
<directory>./src</directory>
1318
</include>
14-
</coverage>
19+
</source>
1520
</phpunit>

src/PHPBuiltInFunctions.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ public function pcntl_async_signals($on = null): MethodProphecy
325325
* @since 4.1.0
326326
* @since 5.0
327327
*/
328-
public function pcntl_signal($signo, callable $handler, bool $restart_syscalls = null): MethodProphecy
328+
public function pcntl_signal(int $signo, callable|int $handler, ?bool $restart_syscalls = null): MethodProphecy
329329
{
330330
return $this->__call('pcntl_signal', func_get_args());
331331
}

src/PHPProphet.php

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

33
namespace HJerichen\ProphecyPHP;
44

5+
use Prophecy\Exception\Prediction\PredictionException;
56
use Prophecy\Prophet;
67
use SebastianBergmann\Template\Template;
78

@@ -10,13 +11,12 @@
1011
*/
1112
class PHPProphet
1213
{
13-
private Prophet $prophet;
1414
/** @var NamespaceProphecy[] */
1515
private array $namespaceProphecies = [];
1616

17-
public function __construct(Prophet $prophet)
18-
{
19-
$this->prophet = $prophet;
17+
public function __construct(
18+
public readonly Prophet $prophet
19+
) {
2020
}
2121

2222
public function prophesize(string $namespace): NamespaceProphecy
@@ -36,6 +36,7 @@ public function prophesize(string $namespace): NamespaceProphecy
3636
return $this->namespaceProphecies[$namespace];
3737
}
3838

39+
/** @throws PredictionException */
3940
public function checkPredictions(): void
4041
{
4142
$this->prophet->checkPredictions();
@@ -47,4 +48,9 @@ public function unReveal(): void
4748
$namespaceProphecy->unReveal();
4849
}
4950
}
51+
52+
public function __destruct()
53+
{
54+
$this->unReveal();
55+
}
5056
}

src/PHPProphetTrait.php

Lines changed: 62 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,61 @@
22

33
namespace HJerichen\ProphecyPHP;
44

5+
use PHPUnit\Framework\AssertionFailedError;
6+
use PHPUnit\Framework\Attributes\After;
7+
use PHPUnit\Framework\Attributes\PostCondition;
58
use PHPUnit\Framework\TestCase;
9+
use Prophecy\Exception\Prediction\PredictionException;
10+
use Prophecy\Prophecy\MethodProphecy;
611
use Prophecy\Prophet;
7-
use ReflectionException;
8-
use ReflectionMethod;
912

1013
/**
1114
* @author Heiko Jerichen <[email protected]>
1215
*/
1316
trait PHPProphetTrait
1417
{
1518
private PHPProphet $phpProphet;
19+
private bool $phpProphecyAssertionsCounted = false;
1620

17-
/**
18-
* @param string $namespace
19-
* @return NamespaceProphecy
20-
* @throws ReflectionException
21-
*/
2221
private function prophesizePHP(string $namespace): NamespaceProphecy
2322
{
2423
return $this->getPHPProphet()->prophesize($namespace);
2524
}
2625

2726
/**
28-
* @return PHPProphet
29-
* @throws ReflectionException
27+
* @postCondition
28+
*/
29+
#[PostCondition]
30+
protected function verifyPhpProphecyDoubles(): void
31+
{
32+
if ($this->prophecyIsUsed()) return;
33+
if (!$this->phpProphecyIsUsed()) return;
34+
35+
try {
36+
$this->phpProphet->checkPredictions();
37+
} catch (PredictionException $e) {
38+
throw new AssertionFailedError($e->getMessage());
39+
} finally {
40+
$this->countProphecyAssertions();
41+
}
42+
}
43+
44+
/**
45+
* @after
3046
*/
47+
#[After]
48+
protected function tearDownPhpProphecy(): void
49+
{
50+
try {
51+
if ($this->prophecyIsUsed()) return;
52+
if (!$this->phpProphecyIsUsed()) return;
53+
if ($this->phpProphecyAssertionsCounted) return;
54+
$this->countProphecyAssertions();
55+
} finally {
56+
unset($this->phpProphet);
57+
}
58+
}
59+
3160
private function getPHPProphet(): PHPProphet
3261
{
3362
if (!isset($this->phpProphet)) {
@@ -36,30 +65,35 @@ private function getPHPProphet(): PHPProphet
3665
return $this->phpProphet;
3766
}
3867

39-
/**
40-
* @return Prophet
41-
* @throws ReflectionException
42-
*/
4368
private function getProphetFromTestCase(): Prophet
4469
{
45-
$refectionMethod = new ReflectionMethod(TestCase::class, 'getProphet');
46-
$refectionMethod->setAccessible(true);
47-
return $refectionMethod->invoke($this);
70+
return $this->prophet ?? new Prophet();
4871
}
4972

50-
/**
51-
* @noinspection PhpUnused
52-
* @noinspection UnknownInspectionInspection
53-
* @noinspection PhpUnhandledExceptionInspection
54-
* @noinspection PhpUndefinedClassInspection
55-
*/
56-
public function runBare(): void
73+
private function prophecyIsUsed(): bool
5774
{
58-
try {
59-
parent::runBare();
60-
} finally {
61-
if (isset($this->phpProphet)) {
62-
$this->phpProphet->unReveal();
75+
return isset($this->prophet) || isset($this->prophecyAssertionsCounted);
76+
}
77+
78+
private function phpProphecyIsUsed(): bool
79+
{
80+
return isset($this->phpProphet);
81+
}
82+
83+
/** @internal */
84+
private function countProphecyAssertions(): void
85+
{
86+
assert($this instanceof TestCase);
87+
assert($this->phpProphet !== null);
88+
$this->phpProphecyAssertionsCounted = true;
89+
90+
foreach ($this->phpProphet->prophet->getProphecies() as $objectProphecy) {
91+
foreach ($objectProphecy->getMethodProphecies() as $methodProphecies) {
92+
foreach ($methodProphecies as $methodProphecy) {
93+
assert($methodProphecy instanceof MethodProphecy);
94+
95+
$this->addToAssertionCount(count($methodProphecy->getCheckedPredictions()));
96+
}
6397
}
6498
}
6599
}

tests/Integration/IntegrationTest.php

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use PHPUnit\Framework\TestCase;
1212
use Prophecy\Argument;
1313
use Prophecy\Exception\Prediction\PredictionException;
14-
use ReflectionProperty;
1514

1615
/**
1716
* @author Heiko Jerichen <[email protected]>
@@ -90,7 +89,6 @@ public function testFunctionWillReturnSimpleWithWrongParameter(): void
9089

9190
$this->expectException(FunctionProphecyNotFoundException::class);
9291

93-
/** @noinspection PhpExpressionResultUnusedInspection */
9492
date('d.m.Y H:i');
9593
}
9694

@@ -109,7 +107,6 @@ public function testFunctionWillReturnSimpleWithMoreThenOneParameterButWithOnyOn
109107

110108
$this->expectException(FunctionProphecyNotFoundException::class);
111109

112-
/** @noinspection PhpExpressionResultUnusedInspection */
113110
date('d.m.Y H:i:s');
114111
}
115112

@@ -126,10 +123,12 @@ public function testFunctionShouldBeCalledNotFulfilled(): void
126123
$this->php->file_put_contents('/tmp/test.txt', 'test')->shouldBeCalled();
127124
$this->php->reveal();
128125

129-
$this->resetProphecy();
130-
131-
$this->expectException(PredictionException::class);
132-
$this->phpProphet->checkPredictions();
126+
try {
127+
$this->expectException(PredictionException::class);
128+
$this->phpProphet->checkPredictions();
129+
} finally {
130+
$this->resetProphecy();
131+
}
133132
}
134133

135134
public function testOverwriteProphecy(): void
@@ -151,6 +150,7 @@ public function testCalculateCorrectProphecy(): void
151150
self::assertEquals('2019', date('Y'));
152151
}
153152

153+
/** @noinspection PhpUnreachableStatementInspection */
154154
public function testExit(): void
155155
{
156156
$exception = new BadFunctionCallException('Function "exit" can not be mocked.');
@@ -160,6 +160,7 @@ public function testExit(): void
160160
$this->php->reveal();
161161
}
162162

163+
/** @noinspection PhpUnreachableStatementInspection */
163164
public function testDie(): void
164165
{
165166
$exception = new BadFunctionCallException('Function "die" can not be mocked.');
@@ -174,10 +175,6 @@ public function testDie(): void
174175

175176
private function resetProphecy(): void
176177
{
177-
$reflectionProperty = new ReflectionProperty(TestCase::class, 'prophet');
178-
$reflectionProperty->setAccessible(true);
179-
180-
/** @noinspection PhpRedundantOptionalArgumentInspection */
181-
$reflectionProperty->setValue($this, null);
178+
unset($this->prophet, $this->phpProphet);
182179
}
183180
}

0 commit comments

Comments
 (0)