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

12,078

Solution 1

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

Solution 2

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).

Share:
12,078

Related videos on Youtube

Hirnhamster
Author by

Hirnhamster

Usual stack: Ubuntu / Debian PHP MySQL Redis Laravel More at https://www.pascallandau.com/.

Updated on June 04, 2022

Comments

  • Hirnhamster
    Hirnhamster almost 2 years

    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.

  • Supericy
    Supericy over 9 years
    If you're mocking methods as well, you can use /** @var InterfaceA|PHPUnit_Framework_MockObject_MockObject */, so it typehints for both classes.
  • Percutio
    Percutio over 9 years
    +1 @Supericy, the mocked object also inherits the Mock Object interface method expects(), which would bring back phpStorm to complain the method is not found if you ignore specifying both InterfaceA and \PHPUnit_Framework_MockObject_MockObject
  • Philippe CARLE
    Philippe CARLE over 8 years
    Bad thing is that CI tools like Scrutinizer will read these annotations and consider your mock variable as an issue because (e.g.) "The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in InterfaceA". It will be marked as an issue and your code rating will be affected… !
  • Steve
    Steve about 8 years
  • edigu
    edigu almost 5 years
    IMHO introducing new interfaces to the software to be able to keep the IDE happy is utterly wrong. IDE should be adapted for the development use case, not the software itself. Adding an inline docblock TypeA|TypeB as recommended in the accepted answer is way to go.