Open
Description
Given
class MyClass
{
public function foo(): string {}
}
class MyOtherClassTest extends \PHPUnit\Framework\TestCase
{
public function testFooMock()
{
$class = $this->createMock(MyClass::class);
$class
->expects(static::once())
->method('foo')
->willReturn(123)
;
}
}
PHPUnit reports:
PHPUnit 8.2.0 by Sebastian Bergmann and contributors.
W 1 / 1 (100%)
Time: 173 ms, Memory: 16.00 MB
There was 1 warning:
1) MyOtherClassTest::testFooMock
Method foo may not return value of type int
WARNINGS!
Tests: 1, Assertions: 0, Warnings: 1.
It would be awesome if PHPStan could report this errors too.
Metadata
Metadata
Assignees
Labels
No labels
Activity
ondrejmirtes commentedon Jun 14, 2019
This is a good idea. Can you take a look at it?
Slamdunk commentedon Jun 14, 2019
Here we would have 3 involved parts:
$class
objectmethod
method with its argumentwillReturn
method with its argument.I have no idea where to start a Rule like this. Anything similar you can point us out?
ondrejmirtes commentedon Jun 14, 2019
After:
$class
isMyClass&MockObject
.expects()
returns InvocationMocker. You'd need to writeInvocationMockerType
(extendsObjectType
) that contains the mocked class + dynamic return type extension that makes sure that$mockObject->expects()
returnsInvocationMockerType
.Then you'd need to write another dynamic return type extension that makes sure that methods called on
InvocationMockerType
return the same type so thatInvocationMockerType
preserved across multiple calls.Also,
InvocationMockerType
should probably have a second constructor argument with a method name. Once you call->method()
, it should know about both the mocked class and the mocked method.Finally, you'd be able to write a rule that checks that calling
->willReturn
onInvocationMockerType(MyClass, foo)
has the correct argument type.You should check out phpstan-doctrine (https://github.com/phpstan/phpstan-doctrine/tree/master/src/Type/Doctrine/QueryBuilder), there's a lot of similar code that analyses DQLs.
Slamdunk commentedon Jun 14, 2019
Great help 👍