Merge pull request #914 from rectorphp/will-phpunit

[PHPUnit] Add UseSpecificWillMethodRector
This commit is contained in:
Tomáš Votruba 2018-12-31 23:06:45 +01:00 committed by GitHub
commit 4ff1d903a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 283 additions and 0 deletions

View File

@ -0,0 +1,2 @@
services:
Rector\PHPUnit\Rector\MethodCall\UseSpecificWillMethodRector: ~

View File

@ -1048,6 +1048,30 @@ Change assertContains()/assertNotContains() method to new string and iterable al
<br>
### `UseSpecificWillMethodRector`
- class: `Rector\PHPUnit\Rector\MethodCall\UseSpecificWillMethodRector`
Changes ->will($this->xxx()) to one specific method
```diff
class SomeClass extends PHPUnit\Framework\TestCase
{
public function test()
{
$translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
$translator->expects($this->any())
->method('trans')
- ->with($this->equalTo('old max {{ max }}!'))
- ->will($this->returnValue('translated max {{ max }}!'));
+ ->with('old max {{ max }}!')
+ ->willReturnValue('translated max {{ max }}!');
}
}
```
<br>
### `SpecificAssertInternalTypeRector`
- class: `Rector\PHPUnit\Rector\MethodCall\SpecificAssertInternalTypeRector`

View File

@ -0,0 +1,129 @@
<?php declare(strict_types=1);
namespace Rector\PHPUnit\Rector\MethodCall;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use Rector\Rector\AbstractPHPUnitRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
/**
* @see https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues/4160
* @see https://github.com/symfony/symfony/pull/29685/files
*/
final class UseSpecificWillMethodRector extends AbstractPHPUnitRector
{
/**
* @var string[]
*/
private $nestedMethodToRenameMap = [
'returnArgument' => 'willReturnArgument',
'returnCallback' => 'willReturnCallback',
'returnSelf' => 'willReturnSelf',
'returnValue' => 'willReturn',
'returnValueMap' => 'willReturnMap',
'throwException' => 'willThrowException',
];
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Changes ->will($this->xxx()) to one specific method', [
new CodeSample(
<<<'CODE_SAMPLE'
class SomeClass extends PHPUnit\Framework\TestCase
{
public function test()
{
$translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
$translator->expects($this->any())
->method('trans')
->with($this->equalTo('old max {{ max }}!'))
->will($this->returnValue('translated max {{ max }}!'));
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class SomeClass extends PHPUnit\Framework\TestCase
{
public function test()
{
$translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
$translator->expects($this->any())
->method('trans')
->with('old max {{ max }}!')
->willReturnValue('translated max {{ max }}!');
}
}
CODE_SAMPLE
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [MethodCall::class];
}
/**
* @param MethodCall $node
*/
public function refactor(Node $node): ?Node
{
if (! $this->isInTestClass($node)) {
return null;
}
if (! $this->isType($node, 'PHPUnit\Framework\MockObject\Builder\InvocationMocker')) {
return null;
}
if ($this->isNameInsensitive($node, 'with')) {
return $this->processWithCall($node);
}
if ($this->isNameInsensitive($node, 'will')) {
return $this->processWillCall($node);
}
return null;
}
private function processWithCall(MethodCall $methodCallNode): ?MethodCall
{
foreach ($methodCallNode->args as $i => $argNode) {
if ($argNode->value instanceof MethodCall && $this->isName($argNode->value, 'equalTo')) {
$methodCallNode->args[$i] = $argNode->value->args[0];
}
}
return $methodCallNode;
}
private function processWillCall(MethodCall $methodCallNode): ?MethodCall
{
if (! $methodCallNode->args[0]->value instanceof MethodCall) {
return null;
}
$nestedMethodCall = $methodCallNode->args[0]->value;
foreach ($this->nestedMethodToRenameMap as $oldMethodName => $newParentMethodName) {
if ($this->isNameInsensitive($nestedMethodCall, $oldMethodName)) {
$methodCallNode->name = new Identifier($newParentMethodName);
// move args up
$methodCallNode->args = $nestedMethodCall->args;
return $methodCallNode;
}
}
return null;
}
}

View File

@ -0,0 +1,74 @@
<?php
namespace Rector\PHPUnit\Tests\Rector\MethodCall\UseSpecificWillMethodRector\Fixture;
class SomeClass extends \PHPUnit\Framework\TestCase
{
public function test()
{
$translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
$translator->expects($this->any())
->method('trans')
->will($this->returnValue('translated max {{ max }}!'));
$translator->expects($this->any())
->will($this->returnSelf());
$translator->expects($this->any())
->will($this->returnArgument(2));
$translator->expects($this->any())
->will($this->returnCallback("str_rot13"));
$translator->expects($this->any())
->will($this->returnValueMap(["a", "b", "c", "d"]));
$translator->expects($this->any())
->WILL($this->returnValue(1));
$translator->expects($this->any())
->will($this->ReturnVALUE(2));
$translator->expects($this->any())
->will($this->throwException(new \InvalidArgumentException()));
}
}
?>
-----
<?php
namespace Rector\PHPUnit\Tests\Rector\MethodCall\UseSpecificWillMethodRector\Fixture;
class SomeClass extends \PHPUnit\Framework\TestCase
{
public function test()
{
$translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
$translator->expects($this->any())
->method('trans')
->willReturn('translated max {{ max }}!');
$translator->expects($this->any())->willReturnSelf();
$translator->expects($this->any())
->willReturnArgument(2);
$translator->expects($this->any())
->willReturnCallback("str_rot13");
$translator->expects($this->any())
->willReturnMap(["a", "b", "c", "d"]);
$translator->expects($this->any())
->willReturn(1);
$translator->expects($this->any())
->willReturn(2);
$translator->expects($this->any())
->willThrowException(new \InvalidArgumentException());
}
}
?>

View File

@ -0,0 +1,35 @@
<?php
namespace Rector\PHPUnit\Tests\Rector\MethodCall\UseSpecificWillMethodRector\Fixture;
class With extends \PHPUnit\Framework\TestCase
{
public function test()
{
$translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
$translator->expects($this->any())
->method('trans')
->with($this->equalTo('old max {{ max }}!'))
->with($this->equalTo($log), $this->equalTo($parameters));
}
}
?>
-----
<?php
namespace Rector\PHPUnit\Tests\Rector\MethodCall\UseSpecificWillMethodRector\Fixture;
class With extends \PHPUnit\Framework\TestCase
{
public function test()
{
$translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
$translator->expects($this->any())
->method('trans')
->with('old max {{ max }}!')
->with($log, $parameters);
}
}
?>

View File

@ -0,0 +1,19 @@
<?php declare(strict_types=1);
namespace Rector\PHPUnit\Tests\Rector\MethodCall\UseSpecificWillMethodRector;
use Rector\PHPUnit\Rector\MethodCall\UseSpecificWillMethodRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
final class UseSpecificWillMethodRectorTest extends AbstractRectorTestCase
{
public function test(): void
{
$this->doTestFiles([__DIR__ . '/Fixture/will.php.inc', __DIR__ . '/Fixture/with.php.inc']);
}
protected function getRectorClass(): string
{
return UseSpecificWillMethodRector::class;
}
}