Skip to content

[Feature request] Report willReturn values incompatible with method signature #48

Open
@Slamdunk

Description

@Slamdunk

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.

Activity

ondrejmirtes

ondrejmirtes commented on Jun 14, 2019

@ondrejmirtes
Member

This is a good idea. Can you take a look at it?

Slamdunk

Slamdunk commented on Jun 14, 2019

@Slamdunk
Author

Here we would have 3 involved parts:

  1. the $class object
  2. the method method with its argument
  3. the willReturn method with its argument.

I have no idea where to start a Rule like this. Anything similar you can point us out?

ondrejmirtes

ondrejmirtes commented on Jun 14, 2019

@ondrejmirtes
Member

After:

$class = $this->createMock(MyClass::class);

$class is MyClass&MockObject.

expects() returns InvocationMocker. You'd need to write InvocationMockerType (extends ObjectType) that contains the mocked class + dynamic return type extension that makes sure that $mockObject->expects() returns InvocationMockerType.

Then you'd need to write another dynamic return type extension that makes sure that methods called on InvocationMockerType return the same type so that InvocationMockerType 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 on InvocationMockerType(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

Slamdunk commented on Jun 14, 2019

@Slamdunk
Author

Great help 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      [Feature request] Report willReturn values incompatible with method signature · Issue #48 · phpstan/phpstan-phpunit