Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent PhpStorm from showing an Expected... warning when using PHPUnit mocks?

When mocking an interface in PHPUnit, PhpStorm complains when it's used as parameter for a type-hinted function.

Example

interface InterfaceA{                                

}                                                    

class ClassA{                                        
    public function foo(InterfaceA $foo){}           
}                                                    

class PhpStormTest extends PHPUnit_Framework_TestCase
{                                                    
    public function testFoo(){                       
        $mock = $this->getMock("InterfaceA");        
        $a = new ClassA();                           
        $a->foo($mock);                              
    }                                                
}   

On $a->foo($mock); PhpStorm underlines $mock with the warning Expected InterfaceA, got PHPUnit_Framework_MockObject_MockObject

Image

PhpStorm warning when using PHPUnit Mock

I guess it's happening because PHPUnit creates the mock a runtime and PhpStorm cannot know that it's actually implementing the interface.

like image 602
Hirnhamster Avatar asked Aug 23 '14 17:08

Hirnhamster


2 Answers

I found a workaround to this problem in the Jetbrain blog at PhpStorm Type Inference and Mocking Frameworks. The important part:

By default, PhpStorm is capable of figuring out the available methods on the mock object. However, it only displays those for PHPUnit’s PHPUnit_Framework_MockObject_MockObject class. Fortunately, we can solve this by instructing PhpStorm to infer type information from other classes as well, by using a simple docblock comment.

So to make the warning disappear, we need to add /** @var InterfaceA */ /** @var InterfaceA|PHPUnit_Framework_MockObject_MockObject */ (cudos to Supericy) to let PhpStorm know our mock actually implements InterfaceA:

interface InterfaceA{                                

}                                                    

class ClassA{                                        
    public function foo(InterfaceA $foo){}           
}                                                    

class PhpStormTest extends PHPUnit_Framework_TestCase
{                                                    
    public function testFoo(){   
        /** @var InterfaceA|PHPUnit_Framework_MockObject_MockObject */            
        $mock = $this->getMock("InterfaceA");        
        $a = new ClassA();                           
        $a->foo($mock);                              
    }                                                
} 

This bugged me for some time, hope it helps someone :)

Edit

Since PHPUnit_Framework_MockObject_MockObject is really ugly to type, you can abbreviate it via MOOMOO and let PHPStorms auto-complete do the rest:

enter image description here

like image 97
Hirnhamster Avatar answered Nov 17 '22 17:11

Hirnhamster


Another plugin I have used for this is the Dynamic Return Type Plugin, it lets you configure return types of methods in a very dynamic way (the example is to have better type information from Mocks).

like image 1
Steve R Avatar answered Nov 17 '22 15:11

Steve R