Skip to content
This repository was archived by the owner on Feb 20, 2023. It is now read-only.

Commit b55fb24

Browse files
Closes #406
1 parent 0dbdc7c commit b55fb24

File tree

3 files changed

+140
-3
lines changed

3 files changed

+140
-3
lines changed

ChangeLog.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# ChangeLog
2+
3+
All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
4+
5+
## [6.0.1] - 2018-02-15
6+
7+
### Fixed
8+
9+
* Fixed [#406](https://github.com/sebastianbergmann/phpunit-mock-objects/issues/406): `parent` return type declaration is not handled correctly
10+
11+
## [6.0.0] - 2018-02-01
12+
13+
[6.0.0]: https://github.com/sebastianbergmann/phpunit-mock-objects/compare/5.0...6.0.0

src/Generator.php

+23-3
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,8 @@ private function generateMockedMethodDefinitionFromExisting(ReflectionMethod $me
979979
* @param bool|string $deprecation
980980
* @param bool $allowsReturnNull
981981
*
982+
* @throws \ReflectionException
983+
* @throws \PHPUnit\Framework\MockObject\RuntimeException
982984
* @throws \InvalidArgumentException
983985
*
984986
* @return string
@@ -1001,13 +1003,31 @@ private function generateMockedMethodDefinition($className, $methodName, $cloneA
10011003
}
10021004
}
10031005

1004-
// Mocked interfaces returning 'self' must explicitly declare the
1005-
// interface name as the return type. See
1006-
// https://bugs.php.net/bug.php?id=70722
1006+
// @see https://bugs.php.net/bug.php?id=70722
10071007
if ($returnType === 'self') {
10081008
$returnType = $className;
10091009
}
10101010

1011+
// @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/406
1012+
if ($returnType === 'parent') {
1013+
$reflector = new ReflectionClass($className);
1014+
1015+
$parentClass = $reflector->getParentClass();
1016+
1017+
if ($parentClass === null) {
1018+
throw new RuntimeException(
1019+
\sprintf(
1020+
'Cannot mock %s::%s because "parent" return type declaration is used but %s does not have a parent class',
1021+
$className,
1022+
$methodName,
1023+
$className
1024+
)
1025+
);
1026+
}
1027+
1028+
$returnType = $parentClass->getName();
1029+
}
1030+
10111031
if (false !== $deprecation) {
10121032
$deprecation = "The $className::$methodName method is deprecated ($deprecation).";
10131033
$deprecationTemplate = $this->getTemplate('deprecation.tpl');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
--TEST--
2+
\PHPUnit\Framework\MockObject\Generator::generate('Bar', [], 'MockBar', true, true)
3+
--FILE--
4+
<?php
5+
abstract class Foo
6+
{
7+
abstract public function baz();
8+
}
9+
10+
class Bar extends Foo
11+
{
12+
public function baz(): parent
13+
{
14+
}
15+
}
16+
17+
require __DIR__ . '/../../vendor/autoload.php';
18+
19+
$generator = new \PHPUnit\Framework\MockObject\Generator;
20+
21+
$mock = $generator->generate(
22+
'Bar',
23+
[],
24+
'MockBar',
25+
true,
26+
true
27+
);
28+
29+
print $mock['code'];
30+
--EXPECT--
31+
class MockBar extends Bar implements PHPUnit\Framework\MockObject\MockObject
32+
{
33+
private $__phpunit_invocationMocker;
34+
private $__phpunit_originalObject;
35+
private $__phpunit_configurable = ['baz'];
36+
37+
public function __clone()
38+
{
39+
$this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
40+
}
41+
42+
public function baz(): Foo
43+
{
44+
$arguments = [];
45+
$count = func_num_args();
46+
47+
if ($count > 0) {
48+
$_arguments = func_get_args();
49+
50+
for ($i = 0; $i < $count; $i++) {
51+
$arguments[] = $_arguments[$i];
52+
}
53+
}
54+
55+
$result = $this->__phpunit_getInvocationMocker()->invoke(
56+
new \PHPUnit\Framework\MockObject\Invocation\ObjectInvocation(
57+
'Bar', 'baz', $arguments, 'Foo', $this, true
58+
)
59+
);
60+
61+
return $result;
62+
}
63+
64+
public function expects(\PHPUnit\Framework\MockObject\Matcher\Invocation $matcher)
65+
{
66+
return $this->__phpunit_getInvocationMocker()->expects($matcher);
67+
}
68+
69+
public function method()
70+
{
71+
$any = new \PHPUnit\Framework\MockObject\Matcher\AnyInvokedCount;
72+
$expects = $this->expects($any);
73+
74+
return call_user_func_array([$expects, 'method'], func_get_args());
75+
}
76+
77+
public function __phpunit_setOriginalObject($originalObject)
78+
{
79+
$this->__phpunit_originalObject = $originalObject;
80+
}
81+
82+
public function __phpunit_getInvocationMocker()
83+
{
84+
if ($this->__phpunit_invocationMocker === null) {
85+
$this->__phpunit_invocationMocker = new \PHPUnit\Framework\MockObject\InvocationMocker($this->__phpunit_configurable);
86+
}
87+
88+
return $this->__phpunit_invocationMocker;
89+
}
90+
91+
public function __phpunit_hasMatchers()
92+
{
93+
return $this->__phpunit_getInvocationMocker()->hasMatchers();
94+
}
95+
96+
public function __phpunit_verify($unsetInvocationMocker = true)
97+
{
98+
$this->__phpunit_getInvocationMocker()->verify();
99+
100+
if ($unsetInvocationMocker) {
101+
$this->__phpunit_invocationMocker = null;
102+
}
103+
}
104+
}

0 commit comments

Comments
 (0)