diff --git a/rules-tests/PHPUnit120/Rector/MethodCall/ExplicitMockExpectsCallRector/Fixture/skip_if_not_test_method.php.inc b/rules-tests/PHPUnit120/Rector/MethodCall/ExplicitMockExpectsCallRector/Fixture/skip_if_not_test_method.php.inc new file mode 100644 index 00000000..bc9f065a --- /dev/null +++ b/rules-tests/PHPUnit120/Rector/MethodCall/ExplicitMockExpectsCallRector/Fixture/skip_if_not_test_method.php.inc @@ -0,0 +1,15 @@ +createMock(\stdClass::class); + + $someClass->method('some'); + } +} diff --git a/rules/PHPUnit120/Rector/MethodCall/ExplicitMockExpectsCallRector.php b/rules/PHPUnit120/Rector/MethodCall/ExplicitMockExpectsCallRector.php index d6b417af..eae0abfb 100644 --- a/rules/PHPUnit120/Rector/MethodCall/ExplicitMockExpectsCallRector.php +++ b/rules/PHPUnit120/Rector/MethodCall/ExplicitMockExpectsCallRector.php @@ -4,16 +4,15 @@ namespace Rector\PHPUnit\PHPUnit120\Rector\MethodCall; +use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node; use PhpParser\Node\Arg; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Expr\Variable; use PHPStan\Type\ObjectType; -use Rector\PHPStan\ScopeFetcher; use Rector\PHPUnit\Enum\PHPUnitClassName; use Rector\PHPUnit\NodeAnalyzer\TestsNodeAnalyzer; use Rector\Rector\AbstractRector; -use Rector\ValueObject\MethodName; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -30,7 +29,7 @@ public function __construct( public function getRuleDefinition(): RuleDefinition { return new RuleDefinition( - 'Add explicit expects() to mocks, to make expectations count explicit', + 'Add explicit expects() to method() mock calls, to make expectations count explicit', [ new CodeSample( <<<'CODE_SAMPLE' @@ -69,11 +68,11 @@ public function testMe() */ public function getNodeTypes(): array { - return [MethodCall::class]; + return [ClassMethod::class]; } /** - * @param MethodCall $node + * @param ClassMethod $node */ public function refactor(Node $node): Node|null { @@ -81,27 +80,42 @@ public function refactor(Node $node): Node|null return null; } - $scope = ScopeFetcher::fetch($node); - if ($scope->getFunctionName() === MethodName::SET_UP) { + if (! $this->testsNodeAnalyzer->isTestClassMethod($node)) { return null; } - if (! $node->var instanceof Variable) { - return null; - } + $hasChanged = false; - if (! $this->isName($node->name, 'method')) { - return null; - } + $this->traverseNodesWithCallable((array) $node->stmts, function (Node $node) use (&$hasChanged): ?MethodCall { + if (! $node instanceof MethodCall) { + return null; + } - if (! $this->isObjectType($node->var, new ObjectType(PHPUnitClassName::MOCK_OBJECT))) { - return null; - } + if (! $node->var instanceof Variable) { + return null; + } - $node->var = new MethodCall($node->var, 'expects', [ - new Arg(new MethodCall(new Variable('this'), 'atLeastOnce')), - ]); + if (! $this->isName($node->name, 'method')) { + return null; + } + + if (! $this->isObjectType($node->var, new ObjectType(PHPUnitClassName::MOCK_OBJECT))) { + return null; + } + + $node->var = new MethodCall($node->var, 'expects', [ + new Arg(new MethodCall(new Variable('this'), 'atLeastOnce')), + ]); + + $hasChanged = true; + + return $node; + }); + + if ($hasChanged) { + return $node; + } - return $node; + return null; } }