phpstan-mockery
phpstan-mockery copied to clipboard
Missing mock type information for Mockery\Expectation::getMock()
Mockery::mock() returns a Mockery\MockInterface. MockInterface::shouldReceive() et al returns an Mockery\Expectation, which in turn has a getMock() method to return the MockInterface the Expectation belongs to.
The problem is that phpstan says the return type of Expectation::getMock() is Mockery\MockInterface with no type information on what was originally mocked. So for example
interface A {
foo(): void
}
function getMock(): A
{
return Mockery::mock(A::class)
->shouldReceive('foo')
->getMock();
}
will cause the following phpstan error: Function getMock() should return A but returns Mockery\MockInterface.
Of course the code in getMock() can be rewritten to not be fluent so that the return value of Mockery::mock() is returned instead, however in many cases I mock objects inline in some other expression and when I do that it's really helpful to be able to use the fluent way of writing the expectations.
Is it possible to change the type of the return value of Mockery\Expectation::getMock() to include the type information of the original mock? With generics I guess it should be something like Mockery::mock(T): MockInterface<T>, MockInterface<T>::shouldReceive(): Expectation<T> and Expectation<T>::getMock(): MockInterface<T>.
The problem is that non of these classes/interfaces are currently generic. The mocks are intersection types. We could probably make Expectation generic with T, and we could write a dynamic return type extension for shouldReceive so that when called on MockInterface&Foo, it returns Expectation<Foo>.