Haehnchen / idea-php-phpunit-plugin

IntelliJ IDEA / PhpStorm PHPUnit Enhancement Plugin
MIT License
55 stars 11 forks source link
intellij intellij-plugin jetbrains mock mocking php phpstorm phpstorm-plugin phpunit prophecy testing

IntelliJ IDEA / PhpStorm PHPUnit Enhancement

Build Status Version Downloads Downloads last month Donate to this project using Paypal

PhpStorm plugin to provide smart autocomplete, code navigation and refactoring features for mocked class methods. Supported all versions of PhpStorm since 2017.1

Key Value
Plugin Url https://plugins.jetbrains.com/plugin/9674
ID de.espend.idea.php.phpunit
Changelog CHANGELOG
Build and Deployment MAINTENANCE
Origin Fork maxfilatov/phpuaca

Installation

Stable version, JetBrains repository:

Feature list

Mocks

/** @var $x \PHPUnit\Framework\TestCase */
$x->createMock(Foo::class)->bar();
/** @var $x \PHPUnit\Framework\TestCase */
$x->prophesize(Foo::class)->bar();
class Foo extends \PHPUnit\Framework\TestCase
{
   public function foobar()
   {
       $foo = $this->createMock(Foo::class);
       $foo->method('<caret>')
   }
}
class Foo extends \PHPUnit\Framework\TestCase
{
   public function testFoo()
   {
       $bar = $this->createPartialMock(\\Foo\Bar::class, ['<caret>']);
   }
}
class Foo extends \PHPUnit\Framework\TestCase
{
   public function setUp()
   {
       $this->foo = $this->createMock('Foo\Bar');
   }
   public function foobar()
   {
       $this->foo->method('<caret>');
   }
}
class FooTest extends \PHPUnit\Framework\TestCase
    {
        public function setUp()
        {
            $this->foo = $this->prophesize(Foo::class);
        }
        public function testFoobar()
        {
            $this->foo->getBar()->willReturn();
        }
    }
class FooTest extends \PHPUnit\Framework\TestCase
    {
        public function setUp()
        {
            $this->foo = $this->getMockBuilder(\Foo::class);
        }
        public function testFoobar()
        {
            $this->foo->getMock()->bar();
        }
    }

Prophecy

class FooTest extends \PHPUnit\Framework\TestCase
{
    public function testFoobar()
    {
        $foo = $this->prophesize(Foo::class);
        $foo->getBar()->willReturn();
    }
}
class FooTest extends \PHPUnit\Framework\TestCase
{
    public function setUp()
    {
        $this->foo = $this->prophesize(Foo::class);
    }

    public function testFoobar()
    {
        $this->foo->getBar()->willReturn();
    }
}
class FooTest extends \PHPUnit\Framework\TestCase
    {
        public function testFoobar()
        {
            $foo = $this->prophesize(Foo::class);
            $foo->reveal()->getBar();
        }
    }

Intention / Generator

Use intention / generator to add new method mocks. Every caret position inside a mock object is detected

$foo = $this->getMockBuilder(Foobar::class)->getMock();
$foo->method('getFoobar')->willReturn();

$foo = $this->createMock(Foobar::class);
$foo->method('getFoobar')->willReturn();
$this->foobar = $this->getMockBuilder(Foobar::class)->getMock();
// ...
$this->foobar->method('getFoobar')->willReturn();

$this->foobar = $this->createMock(Foobar::class);
// ...
$this->foobar->method('getFoobar')->willReturn();
new Foobar();
// ...
new Foobar(
    $this->createMock(Foo::class),
    $this->createMock(FooBar::class)
);
/**
 * @expectedException \Foo\FooException
 */
public function testExpectedException()
{
    $foo = new FooBar();
    $foo->throwFooException();
}

Examples

PHPUnit_Framework_MockObject_MockBuilder::setMethods

PHPUnit_Framework_MockObject_Builder_InvocationMocker::method

PHPUnit_Framework_MockObject_Builder_InvocationMocker::method

PHPUnit Runner LineMarker

PHPUnit Prophecy

PHPUnitExpected exception

Mockery Support

Mockery Support

Mockery

Has support for

Referencing

In the following code snippets referencing, autocompletion, and refactoring are supported at the carets. Note that these all work with aliases, overloaded mocks, proxies, and partial mocks.

class Foo extends Mockery\Adapter\Phpunit\MockeryTestCase
{
    protected function setUp(): void
    {
        $mock = Mockery::mock('MockeryPlugin\DemoProject\Dependency');
        $mock->allows('fo<caret>o');
        $mock->expects('f<caret>oo');
        $mock->shouldReceive('ba<caret>r');
        $mock->shouldNotReceive('b<caret>ar');
    }
}
class Foo extends Mockery\Adapter\Phpunit\MockeryTestCase
{
    protected function setUp(): void
    {
        $this->mock = Mockery::mock('MockeryPlugin\DemoProject\Dependency');
    }

    public function test(): void
    {
        $this->mock->allows('fo<caret>o')->andReturns('result');
    }
}
class Foo extends Mockery\Adapter\Phpunit\MockeryTestCase
{
    protected function setUp(): void
    {
        $mock = Mockery::spy('MockeryPlugin\DemoProject\Dependency');
        // ...
        $mock->shouldHaveReceived('b<caret>ar');
        $mock->shouldNotHaveReceived('fo<caret>o');
    }
}
class Foo extends Mockery\Adapter\Phpunit\MockeryTestCase
{
    protected function setUp(): void
    {
        $mock = Mockery::mock('MockeryPlugin\DemoProject\Dependency');
        $mock->shouldReceive('foo', 'b<caret>ar')
        $mock->shouldReceive([
            'foo' => 'mocked result',
            'ba<caret>r' => 'mocked result'
        ]);
    }
}

Generated Partial Mocks

Method name referencing/refactoring is supported when creating generated partial mocks.

class Foo extends Mockery\Adapter\Phpunit\MockeryTestCase
{
    protected function setUp(): void
    {
        $mock = Mockery::mock(Dependency::class . "[f<caret>oo]");
        $mock = Mockery::mock('MockeryPlugin\DemoProject\Dependency[f<caret>oo]');
    }
}

Method Annotations

A warning highlight is given when the method being used is protected, private, or not found.

class Foo extends Mockery\Adapter\Phpunit\MockeryTestCase
{
    protected function setUp(): void
    {
        $mock = Mockery::mock(Dependency::class);
        $mock->expects('protectedMethod');
        $mock->expects('privateMethod');
        $mock->expects('unknownMethod');
    }
}

Inspection

An inspection is provided which will highlight legacy mockery syntax and provides a quick fix to update. Legacy Mockery uses shouldReceive/shouldNotReceive, and it gets replaced by allows/expects, e.g.

class Foo extends Mockery\Adapter\Phpunit\MockeryTestCase
{
    protected function setUp(): void
    {
        $mock = Mockery::mock(Dependency::class);
        $mock->shouldReceive('foo')->with('arg')->andReturn('result');
        // replaced by
        $mock->allows('foo')->with('arg')->andReturns('result');

        $mock->shouldReceive('foo')->with('arg')->andReturn('result')->once();
        // replaced by
        $mock->expects('foo')->with('arg')->andReturns('result');
    }
}

If a shouldReceive has multiple method parameters then these will get combined into an array parameter. But the inspection can be configured to prefer writing multiple allows/expects statements.

class Foo extends Mockery\Adapter\Phpunit\MockeryTestCase
{
    protected function setUp(): void
    {
        $mock = Mockery::mock(Dependency::class);
        $mock->$this->dependency->shouldReceive('foo', 'bar');
        // replaced by
        $mock->allows(['foo', 'bar']);

        $mock->shouldReceive('foo', 'bar')->andReturns('mocked result');
        // replaced by
        $mock->allows(['foo' => 'mocked result', 'bar' => 'mocked result']);
    }
}
class Foo extends Mockery\Adapter\Phpunit\MockeryTestCase
{
    protected function setUp(): void
    {
        $mock = Mockery::mock(Dependency::class);
        $mock->$this->dependency->shouldReceive('foo', 'bar');
        // replaced by
        $this->dependency->allows('foo');
        $this->dependency->allows('bar');

        $mock->shouldReceive('foo', 'bar')->andReturns('mocked result');
        // replaced by
        $this->dependency->allows('foo')->andReturns('mocked result');
        $this->dependency->allows('bar')->andReturns('mocked result');    }
}

The inspection can also be configured to prefer the new Mockery syntax in which the mocked methods are called like normal rather than as a string.

class Foo extends Mockery\Adapter\Phpunit\MockeryTestCase
{
    protected function setUp(): void
    {
        $mock = Mockery::mock(Dependency::class);
        $mock->shouldReceive('foo')->with('arg')->andReturn('result');
        // replaced by
        $mock->allows()->foo('arg')->andReturns('result');

        $mock->shouldReceive('foo')->with('arg')->andReturn('result')->once();
        // replaced by
        $mock->expects()->foo('arg')->andReturns('result');
    }
}

New Mockery Syntax Type Provider

Type providers are implemented so that when calling allows() on a mock it will have the type of the mocked class. Further allows()->foo() will be given the type Mockery/Expectation so that methods like andReturns(..) work as expected. This extends also to expects(), shouldReceive(), shouldNotReceive() and shouldHaveReceived(). Note: this new syntax does not extend tp shouldNotHaveReceived.

In the following example the first caret has type Dependency, and the second type Expectation.

$mock = Mockery::mock(Dependency::class);
$mock->allows<caret>()->foo<caret>('arg')->andReturns('result');