diff --git a/ChangeLog-8.5.md b/ChangeLog-8.5.md index 79678eed8af..b46f3df57ce 100644 --- a/ChangeLog-8.5.md +++ b/ChangeLog-8.5.md @@ -13,6 +13,7 @@ All notable changes of the PHPUnit 8.5 release series are documented in this fil * [#4663](https://github.com/sebastianbergmann/phpunit/issues/4663): `TestCase::expectError()` works on PHP 7.3, but not on PHP >= 7.4 * [#4678](https://github.com/sebastianbergmann/phpunit/pull/4678): Stubbed methods with `iterable` return types should return empty array by default * [#4692](https://github.com/sebastianbergmann/phpunit/issues/4692): Annotations in single-line doc-comments are not handled correctly +* [#4694](https://github.com/sebastianbergmann/phpunit/issues/4694): `TestCase::getMockFromWsdl()` does not work with PHP 8.1-dev ## [8.5.15] - 2021-03-17 diff --git a/src/Framework/MockObject/MockMethod.php b/src/Framework/MockObject/MockMethod.php index 69e50b2fb73..91a686450cc 100644 --- a/src/Framework/MockObject/MockMethod.php +++ b/src/Framework/MockObject/MockMethod.php @@ -12,15 +12,18 @@ use const DIRECTORY_SEPARATOR; use function implode; use function is_string; +use function method_exists; use function preg_match; use function preg_replace; use function sprintf; +use function str_replace; use function substr_count; use function trim; use function var_export; use ReflectionException; use ReflectionMethod; use ReflectionNamedType; +use ReflectionType; use SebastianBergmann\Type\ObjectType; use SebastianBergmann\Type\Type; use SebastianBergmann\Type\UnknownType; @@ -152,7 +155,7 @@ public static function fromName(string $fullClassName, string $methodName, bool '', false, false, - null, + null ); } @@ -208,13 +211,23 @@ public function generateCode(): string $deprecation = $deprecationTemplate->render(); } + /** + * This is required as the version of sebastian/type used + * by PHPUnit 8.5 does now know about the mixed type. + */ + $returnTypeDeclaration = str_replace( + '?mixed', + 'mixed', + $this->returnType->getReturnTypeDeclaration() + ); + $template = $this->getTemplate($templateFile); $template->setVar( [ 'arguments_decl' => $this->argumentsForDeclaration, 'arguments_call' => $this->argumentsForCall, - 'return_declaration' => $this->returnType->getReturnTypeDeclaration(), + 'return_declaration' => $returnTypeDeclaration, 'arguments_count' => !empty($this->argumentsForCall) ? substr_count($this->argumentsForCall, ',') + 1 : 0, 'class_name' => $this->className, 'method_name' => $this->methodName, @@ -343,19 +356,19 @@ private static function getMethodParametersForCall(ReflectionMethod $method): st private static function deriveReturnType(ReflectionMethod $method): Type { - $returnType = $method->getReturnType(); + $returnType = self::reflectionMethodGetReturnType($method); if ($returnType === null) { return new UnknownType; } // @see https://bugs.php.net/bug.php?id=70722 - if ($returnType->getName() === 'self') { + if ($returnType instanceof ReflectionNamedType && $returnType->getName() === 'self') { return ObjectType::fromName($method->getDeclaringClass()->getName(), $returnType->allowsNull()); } // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/406 - if ($returnType->getName() === 'parent') { + if ($returnType instanceof ReflectionNamedType && $returnType->getName() === 'parent') { $parentClass = $method->getDeclaringClass()->getParentClass(); if ($parentClass === false) { @@ -374,4 +387,17 @@ private static function deriveReturnType(ReflectionMethod $method): Type return Type::fromName($returnType->getName(), $returnType->allowsNull()); } + + private static function reflectionMethodGetReturnType(ReflectionMethod $method): ?ReflectionType + { + if ($method->hasReturnType()) { + return $method->getReturnType(); + } + + if (!method_exists($method, 'getTentativeReturnType')) { + return null; + } + + return $method->getTentativeReturnType(); + } }