Skip to content

Commit

Permalink
Closes #4931 and #4955
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianbergmann committed Aug 29, 2022
1 parent ab74dd8 commit b7c0877
Show file tree
Hide file tree
Showing 14 changed files with 441 additions and 2 deletions.
5 changes: 5 additions & 0 deletions ChangeLog-9.5.md
Expand Up @@ -4,6 +4,11 @@ All notable changes of the PHPUnit 9.5 release series are documented in this fil

## [9.5.24] - 2022-MM-DD

### Added

* [#4931](https://github.com/sebastianbergmann/phpunit/issues/4931): Support `null` and `false` as stand-alone types
* [#4955](https://github.com/sebastianbergmann/phpunit/issues/4955): Support `true` as stand-alone type

### Fixed

* [#4913](https://github.com/sebastianbergmann/phpunit/issues/4913): Failed `assert()` should show a backtrace
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -46,7 +46,7 @@
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^3.0",
"sebastian/type": "^3.1",
"sebastian/version": "^3.0.2"
},
"config": {
Expand Down
4 changes: 4 additions & 0 deletions src/Framework/MockObject/Invocation.php
Expand Up @@ -144,6 +144,10 @@ public function generateReturnValue()
return null;
}

if (in_array('true', $types, true)) {
return true;
}

if (in_array('false', $types, true) ||
in_array('bool', $types, true)) {
return false;
Expand Down
6 changes: 5 additions & 1 deletion src/Framework/MockObject/MockMethod.php
Expand Up @@ -309,7 +309,11 @@ private static function getMethodParametersForDeclaration(ReflectionMethod $meth
}

if ($type !== null) {
if ($typeName !== 'mixed' && $parameter->allowsNull() && !$type instanceof ReflectionIntersectionType && !$type instanceof ReflectionUnionType) {
if ($typeName !== 'mixed' &&
$typeName !== 'null' &&
!$type instanceof ReflectionIntersectionType &&
!$type instanceof ReflectionUnionType &&
$parameter->allowsNull()) {
$nullable = '?';
}

Expand Down
15 changes: 15 additions & 0 deletions tests/_files/mock-object/InterfaceWithMethodReturningFalse.php
@@ -0,0 +1,15 @@
<?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\TestFixture\MockObject;

interface InterfaceWithMethodReturningFalse
{
public function returnsFalse(): false;
}
15 changes: 15 additions & 0 deletions tests/_files/mock-object/InterfaceWithMethodReturningNull.php
@@ -0,0 +1,15 @@
<?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\TestFixture\MockObject;

interface InterfaceWithMethodReturningNull
{
public function returnsNull(): null;
}
15 changes: 15 additions & 0 deletions tests/_files/mock-object/InterfaceWithMethodReturningTrue.php
@@ -0,0 +1,15 @@
<?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\TestFixture\MockObject;

interface InterfaceWithMethodReturningTrue
{
public function returnsTrue(): true;
}
56 changes: 56 additions & 0 deletions tests/end-to-end/mock-objects/generator/parameter_false.phpt
@@ -0,0 +1,56 @@
--TEST--
\PHPUnit\Framework\MockObject\Generator::generate('Foo', [], 'MockFoo', true, true)
--SKIPIF--
<?php declare(strict_types=1);
if (version_compare('8.2.0-dev', PHP_VERSION, '>')) {
print 'skip: PHP 8.2 is required.';
}
--FILE--
<?php declare(strict_types=1);
interface Foo
{
public function bar(false $baz): void;
}

require_once __DIR__ . '/../../../../vendor/autoload.php';

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

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

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

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

public function bar(false $baz): void
{
$__phpunit_arguments = [$baz];
$__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];
}
}

$this->__phpunit_getInvocationHandler()->invoke(
new \PHPUnit\Framework\MockObject\Invocation(
'Foo', 'bar', $__phpunit_arguments, 'void', $this, true
)
);
}
}
56 changes: 56 additions & 0 deletions tests/end-to-end/mock-objects/generator/parameter_null.phpt
@@ -0,0 +1,56 @@
--TEST--
\PHPUnit\Framework\MockObject\Generator::generate('Foo', [], 'MockFoo', true, true)
--SKIPIF--
<?php declare(strict_types=1);
if (version_compare('8.2.0-dev', PHP_VERSION, '>')) {
print 'skip: PHP 8.2 is required.';
}
--FILE--
<?php declare(strict_types=1);
interface Foo
{
public function bar(null $baz): void;
}

require_once __DIR__ . '/../../../../vendor/autoload.php';

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

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

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

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

public function bar(null $baz): void
{
$__phpunit_arguments = [$baz];
$__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];
}
}

$this->__phpunit_getInvocationHandler()->invoke(
new \PHPUnit\Framework\MockObject\Invocation(
'Foo', 'bar', $__phpunit_arguments, 'void', $this, true
)
);
}
}
56 changes: 56 additions & 0 deletions tests/end-to-end/mock-objects/generator/parameter_true.phpt
@@ -0,0 +1,56 @@
--TEST--
\PHPUnit\Framework\MockObject\Generator::generate('Foo', [], 'MockFoo', true, true)
--SKIPIF--
<?php declare(strict_types=1);
if (version_compare('8.2.0-dev', PHP_VERSION, '>')) {
print 'skip: PHP 8.2 is required.';
}
--FILE--
<?php declare(strict_types=1);
interface Foo
{
public function bar(true $baz): void;
}

require_once __DIR__ . '/../../../../vendor/autoload.php';

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

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

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

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

public function bar(true $baz): void
{
$__phpunit_arguments = [$baz];
$__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];
}
}

$this->__phpunit_getInvocationHandler()->invoke(
new \PHPUnit\Framework\MockObject\Invocation(
'Foo', 'bar', $__phpunit_arguments, 'void', $this, true
)
);
}
}
@@ -0,0 +1,58 @@
--TEST--
\PHPUnit\Framework\MockObject\Generator::generate('Foo', [], 'MockFoo', true, true)
--SKIPIF--
<?php declare(strict_types=1);
if (version_compare('8.2.0-dev', PHP_VERSION, '>')) {
print 'skip: PHP 8.2 is required.';
}
--FILE--
<?php declare(strict_types=1);
interface Foo
{
public function bar(): false;
}

require_once __DIR__ . '/../../../../vendor/autoload.php';

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

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

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

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

public function bar(): false
{
$__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', 'bar', $__phpunit_arguments, 'false', $this, true
)
);

return $__phpunit_result;
}
}
@@ -0,0 +1,58 @@
--TEST--
\PHPUnit\Framework\MockObject\Generator::generate('Foo', [], 'MockFoo', true, true)
--SKIPIF--
<?php declare(strict_types=1);
if (version_compare('8.2.0-dev', PHP_VERSION, '>')) {
print 'skip: PHP 8.2 is required.';
}
--FILE--
<?php declare(strict_types=1);
interface Foo
{
public function bar(): null;
}

require_once __DIR__ . '/../../../../vendor/autoload.php';

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

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

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

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

public function bar(): null
{
$__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', 'bar', $__phpunit_arguments, 'null', $this, true
)
);

return $__phpunit_result;
}
}

0 comments on commit b7c0877

Please sign in to comment.