Skip to content

Commit

Permalink
Closes #4938
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianbergmann committed Mar 24, 2022
1 parent 1d2a88d commit c1c9d4d
Show file tree
Hide file tree
Showing 99 changed files with 2,973 additions and 3 deletions.
7 changes: 7 additions & 0 deletions ChangeLog-8.5.md
Expand Up @@ -2,6 +2,12 @@

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

## [8.5.26] - 2022-MM-DD

### Fixed

* [#4938](https://github.com/sebastianbergmann/phpunit/issues/4938): Test Double code generator does not handle `void` return type declaration on `__clone()` methods

## [8.5.25] - 2022-03-16

### Fixed
Expand Down Expand Up @@ -213,6 +219,7 @@ All notable changes of the PHPUnit 8.5 release series are documented in this fil
* [#3967](https://github.com/sebastianbergmann/phpunit/issues/3967): Cannot double interface that extends interface that extends `\Throwable`
* [#3968](https://github.com/sebastianbergmann/phpunit/pull/3968): Test class run in a separate PHP process are passing when `exit` called inside

[8.5.26]: https://github.com/sebastianbergmann/phpunit/compare/8.5.25...8.5
[8.5.25]: https://github.com/sebastianbergmann/phpunit/compare/8.5.24...8.5.25
[8.5.24]: https://github.com/sebastianbergmann/phpunit/compare/8.5.23...8.5.24
[8.5.23]: https://github.com/sebastianbergmann/phpunit/compare/8.5.22...8.5.23
Expand Down
@@ -0,0 +1,21 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Framework\MockObject;

/**
* @internal This trait is not covered by the backward compatibility promise for PHPUnit
*/
trait MockedCloneMethodWithVoidReturnType
{
public function __clone(): void
{
$this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationHandler();
}
}
@@ -0,0 +1,23 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Framework\MockObject;

/**
* @internal This trait is not covered by the backward compatibility promise for PHPUnit
*/
trait UnmockedCloneMethodWithVoidReturnType
{
public function __clone(): void
{
$this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationHandler();

parent::__clone();
}
}
12 changes: 10 additions & 2 deletions src/Framework/MockObject/Generator.php
Expand Up @@ -954,11 +954,19 @@ private function generateMock($type, ?array $explicitMethods, string $mockClassN
$cloneTrait = '';

if ($mockedCloneMethod) {
$cloneTrait = PHP_EOL . ' use \PHPUnit\Framework\MockObject\MockedCloneMethodWithoutReturnType;';
if (PHP_MAJOR_VERSION >= 8) {
$cloneTrait = PHP_EOL . ' use \PHPUnit\Framework\MockObject\MockedCloneMethodWithVoidReturnType;';
} else {
$cloneTrait = PHP_EOL . ' use \PHPUnit\Framework\MockObject\MockedCloneMethodWithoutReturnType;';
}
}

if ($unmockedCloneMethod) {
$cloneTrait = PHP_EOL . ' use \PHPUnit\Framework\MockObject\UnmockedCloneMethodWithoutReturnType;';
if (PHP_MAJOR_VERSION >= 8) {
$cloneTrait = PHP_EOL . ' use \PHPUnit\Framework\MockObject\UnmockedCloneMethodWithVoidReturnType;';
} else {
$cloneTrait = PHP_EOL . ' use \PHPUnit\Framework\MockObject\UnmockedCloneMethodWithoutReturnType;';
}
}

$classTemplate->setVar(
Expand Down
@@ -1,5 +1,10 @@
--TEST--
\PHPUnit\Framework\MockObject\Generator::generate('Foo', [], 'MockFoo', true, true)
--SKIPIF--
<?php declare(strict_types=1);
if (PHP_MAJOR_VERSION >= 8) {
print 'skip: PHP 7 is required.';
}
--FILE--
<?php declare(strict_types=1);
trait BaseTrait
Expand Down
89 changes: 89 additions & 0 deletions tests/end-to-end/mock-objects/generator/232-php8.phpt
@@ -0,0 +1,89 @@
--TEST--
\PHPUnit\Framework\MockObject\Generator::generate('Foo', [], 'MockFoo', true, true)
--SKIPIF--
<?php declare(strict_types=1);
if (PHP_MAJOR_VERSION < 8) {
print 'skip: PHP 8 is required.';
}
--FILE--
<?php declare(strict_types=1);
trait BaseTrait
{
protected function hello()
{
return 'hello';
}
}

trait ChildTrait
{
use BaseTrait
{
hello as private hi;
}

protected function hello()
{
return 'hi';
}

protected function world()
{
return $this->hi();
}
}

class Foo
{
use ChildTrait;

public function speak()
{
return $this->world();
}
}

require_once __DIR__ . '/../../../bootstrap.php';

$generator = new \PHPUnit\Framework\MockObject\Generator;

$mock = $generator->generate(
'Foo',
[],
'MockFoo',
true,
true
);

print $mock->getClassCode();
--EXPECTF--
declare(strict_types=1);

class MockFoo extends Foo implements PHPUnit\Framework\MockObject\MockObject
{
use \PHPUnit\Framework\MockObject\Api;
use \PHPUnit\Framework\MockObject\Method;
use \PHPUnit\Framework\MockObject\MockedCloneMethodWithVoidReturnType;

public function speak()
{
$__phpunit_arguments = [];
$__phpunit_count = func_num_args();

if ($__phpunit_count > 0) {
$__phpunit_arguments_tmp = func_get_args();

for ($__phpunit_i = 0; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
$__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
}
}

$__phpunit_result = $this->__phpunit_getInvocationHandler()->invoke(
new \PHPUnit\Framework\MockObject\Invocation(
'Foo', 'speak', $__phpunit_arguments, '', $this, true
)
);

return $__phpunit_result;
}
}
@@ -1,6 +1,11 @@
--TEST--
https://github.com/sebastianbergmann/phpunit-mock-objects/issues/420
https://github.com/sebastianbergmann/phpunit/issues/3154
--SKIPIF--
<?php declare(strict_types=1);
if (PHP_MAJOR_VERSION >= 8) {
print 'skip: PHP 7 is required.';
}
--FILE--
<?php declare(strict_types=1);
namespace Is\Namespaced;
Expand Down
@@ -0,0 +1,74 @@
--TEST--
https://github.com/sebastianbergmann/phpunit-mock-objects/issues/420
https://github.com/sebastianbergmann/phpunit/issues/3154
--SKIPIF--
<?php declare(strict_types=1);
if (PHP_MAJOR_VERSION < 8) {
print 'skip: PHP 8 is required.';
}
--FILE--
<?php declare(strict_types=1);
namespace Is\Namespaced;
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

const A_CONSTANT = 17;
const PHP_VERSION = "";

class Issue3154
{
public function a(int $i = PHP_INT_MAX, int $j = A_CONSTANT, string $v = \PHP_VERSION, string $z = '#'): string
{
return $z."sum: ".($i+$j).$v;
}
}
require_once __DIR__ . '/../../../bootstrap.php';

$generator = new \PHPUnit\Framework\MockObject\Generator;

$mock = $generator->generate(
Issue3154::class,
[],
'Issue3154Mock',
true,
true
);

print $mock->getClassCode();
--EXPECTF--
declare(strict_types=1);

class Issue3154Mock extends Is\Namespaced\Issue3154 implements PHPUnit\Framework\MockObject\MockObject
{
use \PHPUnit\Framework\MockObject\Api;
use \PHPUnit\Framework\MockObject\Method;
use \PHPUnit\Framework\MockObject\MockedCloneMethodWithVoidReturnType;

public function a(int $i = %d, int $j = 17, string $v = '%s', string $z = '#'): string
{
$__phpunit_arguments = [$i, $j, $v, $z];
$__phpunit_count = func_num_args();

if ($__phpunit_count > 4) {
$__phpunit_arguments_tmp = func_get_args();

for ($__phpunit_i = 4; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
$__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
}
}

$__phpunit_result = $this->__phpunit_getInvocationHandler()->invoke(
new \PHPUnit\Framework\MockObject\Invocation(
'Is\Namespaced\Issue3154', 'a', $__phpunit_arguments, ': string', $this, true
)
);

return $__phpunit_result;
}
}
2 changes: 1 addition & 1 deletion tests/end-to-end/mock-objects/generator/3967.phpt
Expand Up @@ -36,7 +36,7 @@ class MockBaz extends Exception implements Baz, PHPUnit\Framework\MockObject\Moc
{
use \PHPUnit\Framework\MockObject\Api;
use \PHPUnit\Framework\MockObject\Method;
use \PHPUnit\Framework\MockObject\UnmockedCloneMethodWithoutReturnType;
use \PHPUnit\Framework\MockObject\UnmockedCloneMethodWithVoidReturnType;

public function foo(): string
{
Expand Down
@@ -1,5 +1,10 @@
--TEST--
https://github.com/sebastianbergmann/phpunit-mock-objects/issues/397
--SKIPIF--
<?php declare(strict_types=1);
if (PHP_MAJOR_VERSION >= 8) {
print 'skip: PHP 7 is required.';
}
--FILE--
<?php declare(strict_types=1);
class C
Expand Down
60 changes: 60 additions & 0 deletions tests/end-to-end/mock-objects/generator/397-php8.phpt
@@ -0,0 +1,60 @@
--TEST--
https://github.com/sebastianbergmann/phpunit-mock-objects/issues/397
--SKIPIF--
<?php declare(strict_types=1);
if (PHP_MAJOR_VERSION < 8) {
print 'skip: PHP 8 is required.';
}
--FILE--
<?php declare(strict_types=1);
class C
{
public function m(?self $other): self
{
}
}

require_once __DIR__ . '/../../../bootstrap.php';

$generator = new \PHPUnit\Framework\MockObject\Generator;

$mock = $generator->generate(
C::class,
[],
'MockC',
true,
true
);

print $mock->getClassCode();
--EXPECTF--
declare(strict_types=1);

class MockC extends C implements PHPUnit\Framework\MockObject\MockObject
{
use \PHPUnit\Framework\MockObject\Api;
use \PHPUnit\Framework\MockObject\Method;
use \PHPUnit\Framework\MockObject\MockedCloneMethodWithVoidReturnType;

public function m(?C $other): C
{
$__phpunit_arguments = [$other];
$__phpunit_count = func_num_args();

if ($__phpunit_count > 1) {
$__phpunit_arguments_tmp = func_get_args();

for ($__phpunit_i = 1; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
$__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
}
}

$__phpunit_result = $this->__phpunit_getInvocationHandler()->invoke(
new \PHPUnit\Framework\MockObject\Invocation(
'C', 'm', $__phpunit_arguments, ': C', $this, true
)
);

return $__phpunit_result;
}
}
@@ -1,5 +1,10 @@
--TEST--
https://github.com/sebastianbergmann/phpunit/issues/4139
--SKIPIF--
<?php declare(strict_types=1);
if (PHP_MAJOR_VERSION >= 8) {
print 'skip: PHP 7 is required.';
}
--FILE--
<?php declare(strict_types=1);
interface InterfaceWithConstructor
Expand Down

0 comments on commit c1c9d4d

Please sign in to comment.