diff --git a/library/Mockery/Reflector.php b/library/Mockery/Reflector.php index 524d20cd2..bb145de93 100644 --- a/library/Mockery/Reflector.php +++ b/library/Mockery/Reflector.php @@ -192,9 +192,11 @@ private static function typeToString(\ReflectionType $type, \ReflectionClass $de { // PHP 8 union types can be recursively processed if ($type instanceof \ReflectionUnionType) { - return \implode('|', \array_map(function (\ReflectionType $type) use ($declaringClass) { - return self::typeToString($type, $declaringClass); - }, $type->getTypes())); + return \implode('|', \array_filter(\array_map(function (\ReflectionType $type) use ($declaringClass) { + $typeHint = self::typeToString($type, $declaringClass); + + return $typeHint === 'null' ? null : $typeHint; + }, $type->getTypes()))); } // PHP 7.0 doesn't have named types, but 7.1+ does diff --git a/tests/PHP80/Php80LanguageFeaturesTest.php b/tests/PHP80/Php80LanguageFeaturesTest.php index fbecee555..11ffa232e 100644 --- a/tests/PHP80/Php80LanguageFeaturesTest.php +++ b/tests/PHP80/Php80LanguageFeaturesTest.php @@ -29,6 +29,15 @@ public function it_can_mock_a_class_with_a_union_argument_type_hint() $mock->foo($object); } + /** @test */ + public function it_can_mock_a_class_with_a_union_argument_type_hint_including_null() + { + $mock = mock(ArgumentUnionTypeHintWithNull::class); + $mock->allows()->foo(null); + + $mock->foo(null); + } + /** @test */ public function it_can_mock_a_class_with_a_parent_argument_type_hint() { @@ -78,6 +87,13 @@ public function foo(string|array|self $foo) } } +class ArgumentUnionTypeHintWithNull +{ + public function foo(string|array|null $foo) + { + } +} + class ArgumentParentTypeHint extends \stdClass { public function foo(parent $foo)