Skip to content

Commit 7ee9617

Browse files
[PHPUnit12] Skip used as next arg with MockObject Type on ExpressionCreateMockToCreateStubRector (#670)
* [PHPUnit12] Skip used as next arg with MockObject Type on ExpressionCreateMockToCreateStubRector * Fix * [rector] Rector fixes * fix * fix * fix * fix * fix * [rector] Rector fixes * fix * [rector] Rector fixes * final touch: cleanup * final touch: more fixture --------- Co-authored-by: GitHub Action <actions@github.com>
1 parent 389eeab commit 7ee9617

6 files changed

Lines changed: 89 additions & 3 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\PHPUnit120\Rector\ClassMethod\ExpressionCreateMockToCreateStubRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Rector\PHPUnit\Tests\PHPUnit120\Rector\ClassMethod\ExpressionCreateMockToCreateStubRector\Source\ClassWithDependency;
7+
8+
final class SkipUsedAsNextArgMockObjectType extends TestCase
9+
{
10+
public function test()
11+
{
12+
$mock = $this->createMock(ClassWithDependency::class);
13+
$this->configureMock($mock);
14+
}
15+
16+
private function configureMock(\PHPUnit\Framework\MockObject\MockObject $mock)
17+
{
18+
$mock->method('someMethod')->willReturn(1);
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\PHPUnit120\Rector\ClassMethod\ExpressionCreateMockToCreateStubRector\Fixture;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Rector\PHPUnit\Tests\PHPUnit120\Rector\ClassMethod\ExpressionCreateMockToCreateStubRector\Source\ClassWithDependency;
7+
8+
final class SkipUsedAsNextArgMockObjectTypeNamed extends TestCase
9+
{
10+
public function test()
11+
{
12+
$mock = $this->createMock(ClassWithDependency::class);
13+
$this->configureMock(mock: $mock, otherParam: 1);
14+
}
15+
16+
private function configureMock($otherParam, \PHPUnit\Framework\MockObject\MockObject $mock)
17+
{
18+
$mock->method('someMethod')->willReturn(1);
19+
}
20+
}

rules/AnnotationsToAttributes/Rector/ClassMethod/TestWithAnnotationToAttributeRector.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ public function refactor(Node $node): ?Node
129129
// test from doc blocks
130130
$this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $testWithPhpDocTagNode);
131131

132-
/** @var GenericTagValueNode $genericTagValueNode */
133132
$genericTagValueNode = $testWithPhpDocTagNode->value;
134133
$testWithItems = explode("\n", trim($genericTagValueNode->value));
135134

rules/CodeQuality/NodeAnalyser/MockObjectExprDetector.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,24 @@
88
use PhpParser\Node\Expr\MethodCall;
99
use PhpParser\Node\Expr\PropertyFetch;
1010
use PhpParser\Node\Expr\Variable;
11+
use PhpParser\Node\Identifier;
1112
use PhpParser\Node\Stmt\Class_;
1213
use PhpParser\Node\Stmt\ClassMethod;
14+
use PHPStan\Reflection\MethodReflection;
15+
use PHPStan\Type\ObjectType;
1316
use Rector\NodeNameResolver\NodeNameResolver;
1417
use Rector\PhpParser\Node\BetterNodeFinder;
1518
use Rector\PHPUnit\CodeQuality\NodeFinder\VariableFinder;
19+
use Rector\PHPUnit\Enum\PHPUnitClassName;
20+
use Rector\Reflection\ReflectionResolver;
1621

1722
final readonly class MockObjectExprDetector
1823
{
1924
public function __construct(
2025
private BetterNodeFinder $betterNodeFinder,
2126
private NodeNameResolver $nodeNameResolver,
2227
private VariableFinder $variableFinder,
28+
private ReflectionResolver $reflectionResolver,
2329
) {
2430
}
2531

@@ -67,6 +73,8 @@ public function isUsedForMocking(Expr $expr, ClassMethod $classMethod): bool
6773
/** @var array<Expr\MethodCall> $methodCalls */
6874
$methodCalls = $this->betterNodeFinder->findInstancesOfScoped((array) $classMethod->stmts, [MethodCall::class]);
6975

76+
$mockObjectType = new ObjectType(PHPUnitClassName::MOCK_OBJECT);
77+
7078
foreach ($methodCalls as $methodCall) {
7179
if (! $methodCall->var instanceof Variable) {
7280
continue;
@@ -76,6 +84,47 @@ public function isUsedForMocking(Expr $expr, ClassMethod $classMethod): bool
7684
// variable is being called on, most like mocking, lets skip
7785
return true;
7886
}
87+
88+
if ($methodCall->isFirstClassCallable()) {
89+
continue;
90+
}
91+
92+
// check if variable is passed as arg to a method that declares MockObject type parameter
93+
foreach ($methodCall->getArgs() as $argIndex => $arg) {
94+
if (! $arg->value instanceof Variable) {
95+
continue;
96+
}
97+
98+
if (! $this->nodeNameResolver->isName($arg->value, $variableName)) {
99+
continue;
100+
}
101+
102+
$methodReflection = $this->reflectionResolver->resolveMethodReflectionFromMethodCall($methodCall);
103+
if (! $methodReflection instanceof MethodReflection) {
104+
continue;
105+
}
106+
107+
$variants = $methodReflection->getVariants();
108+
foreach ($variants as $variant) {
109+
$parameters = $variant->getParameters();
110+
foreach ($parameters as $parameter) {
111+
$paramType = $parameter->getType();
112+
if ($arg->name instanceof Identifier
113+
&& $this->nodeNameResolver->isName($arg->name, $parameter->getName())
114+
&& $mockObjectType->isSuperTypeOf($paramType)
115+
->yes()) {
116+
return true;
117+
}
118+
}
119+
120+
if (isset($parameters[$argIndex])) {
121+
$paramType = $parameters[$argIndex]->getType();
122+
if ($mockObjectType->isSuperTypeOf($paramType)->yes()) {
123+
return true;
124+
}
125+
}
126+
}
127+
}
79128
}
80129

81130
return false;

rules/CodeQuality/Rector/Class_/AddSeeTestAnnotationRector.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ private function shouldSkipClass(Class_ $class): bool
134134
continue;
135135
}
136136

137-
/** @var GenericTagValueNode $genericTagValueNode */
138137
$genericTagValueNode = $seePhpDocTagNode->value;
139138

140139
$seeTagClass = ltrim($genericTagValueNode->value, '\\');

rules/PHPUnit120/Rector/ClassMethod/ExpressionCreateMockToCreateStubRector.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ public function refactor(Node $node): ?ClassMethod
106106
continue;
107107
}
108108

109-
/** @var Assign $assign */
110109
$assign = $stmt->expr;
111110

112111
if (! $assign->var instanceof Variable) {

0 commit comments

Comments
 (0)