diff --git a/src/Rector/Contrib/PHPUnit/ExceptionRector.php b/src/Rector/Contrib/PHPUnit/ExceptionRector.php index caa2c7e613b..7b3891db598 100644 --- a/src/Rector/Contrib/PHPUnit/ExceptionRector.php +++ b/src/Rector/Contrib/PHPUnit/ExceptionRector.php @@ -3,13 +3,21 @@ namespace Rector\Rector\Contrib\PHPUnit; use PhpParser\Node; +use PhpParser\Node\Arg; use PhpParser\Node\Expr\MethodCall; use Rector\Node\MethodCallNodeFactory; use Rector\NodeAnalyzer\MethodCallAnalyzer; use Rector\Rector\AbstractRector; /** - * Covers ref. https://github.com/RectorPHP/Rector/issues/79 + * Before: + * - $this->setExpectedException(Exception::class, 'Message', 'CODE'); + * + * + * After: + * - $this->setExpectedException(Exception::class); + * - $this->expectExceptionMessage('Message'); + * - $this->expectExceptionCode('CODE'); */ final class ExceptionRector extends AbstractRector { @@ -39,11 +47,16 @@ final class ExceptionRector extends AbstractRector public function isCandidate(Node $node): bool { - return $this->methodCallAnalyzer->isTypesAndMethods( + if (! $this->methodCallAnalyzer->isTypeAndMethods( $node, - ['PHPUnit\Framework\TestCase', 'PHPUnit_Framework_TestCase'], + 'PHPUnit\Framework\TestCase', array_keys($this->oldToNewMethod) - ); + )) { + return false; + } + + /** @var MethodCall $node */ + return isset($node->args[1]); } /** @@ -52,23 +65,34 @@ final class ExceptionRector extends AbstractRector public function refactor(Node $methodCallNode): ?Node { $oldMethodName = $methodCallNode->name->name; - $methodCallNode->name->name = 'expectException'; - if (! isset($methodCallNode->args[1])) { - return $methodCallNode; - } - - $secondArgument = $methodCallNode->args[1]; + $this->prependNewMethodCall( + $methodCallNode, + $this->oldToNewMethod[$oldMethodName], + $methodCallNode->args[1] + ); unset($methodCallNode->args[1]); - $expectExceptionMessageMethodCall = $this->methodCallNodeFactory->createWithVariableNameMethodNameAndArguments( - 'this', - $this->oldToNewMethod[$oldMethodName], - [$secondArgument] - ); - - $this->prependNodeAfterNode($expectExceptionMessageMethodCall, $methodCallNode); + if (isset($methodCallNode->args[2])) { + $this->prependNewMethodCall( + $methodCallNode, + 'expectExceptionCode', + $methodCallNode->args[2] + ); + unset($methodCallNode->args[2]); + } return $methodCallNode; } + + private function prependNewMethodCall(MethodCall $methodCallNode, string $methodName, Arg $argNode): void + { + $expectExceptionMessageMethodCall = $this->methodCallNodeFactory->createWithVariableNameMethodNameAndArguments( + 'this', + $methodName, + [$argNode] + ); + + $this->prependNodeAfterNode($expectExceptionMessageMethodCall, $methodCallNode); + } } diff --git a/src/config/level/phpunit/phpunit60.yml b/src/config/level/phpunit/phpunit60.yml index 2be72c1fb44..4faca600150 100644 --- a/src/config/level/phpunit/phpunit60.yml +++ b/src/config/level/phpunit/phpunit60.yml @@ -1,9 +1,16 @@ rectors: Rector\Rector\Contrib\PHPUnit\ExceptionAnnotationRector: ~ - Rector\Rector\Contrib\PHPUnit\ExceptionRector: ~ Rector\Rector\Contrib\PHPUnit\GetMockRector: ~ Rector\Rector\Contrib\PHPUnit\SpecificMethodRector: ~ # ref. https://github.com/sebastianbergmann/phpunit/compare/5.7.9...6.0.0 Rector\Rector\Dynamic\PseudoNamespaceToNamespaceRector: - 'PHPUnit_' + + # handles 2nd and 3rd arugment of setExpectedException + Rector\Rector\Contrib\PHPUnit\ExceptionRector: ~ + + Rector\Rector\Dynamic\MethodNameReplacerRector: + 'PHPUnit\Framework\TestClass': + 'setExpectedException': 'expectedException' + 'setExpectedExceptionRegExp': 'expectedException'