How to prevent PhpStorm from showing an Expected... warning when using PHPUnit mocks?
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:
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).
Related videos on Youtube
Hirnhamster
Usual stack: Ubuntu / Debian PHP MySQL Redis Laravel More at https://www.pascallandau.com/.
Updated on June 04, 2022Comments
-
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 warningExpected InterfaceA, got PHPUnit_Framework_MockObject_MockObject
Image
I guess it's happening because PHPUnit creates the mock a runtime and PhpStorm cannot know that it's actually implementing the interface.
-
Supericy over 9 yearsIf you're mocking methods as well, you can use
/** @var InterfaceA|PHPUnit_Framework_MockObject_MockObject */
, so it typehints for both classes. -
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 bothInterfaceA
and\PHPUnit_Framework_MockObject_MockObject
-
Philippe CARLE over 8 yearsBad 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 about 8 yearsDocs from phpstorm blog.jetbrains.com/webide/2013/01/…
-
edigu almost 5 yearsIMHO 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.