I need to run tests on a certain class, but adding a method that was not originally present.
Previously this need could be satisfied using MockBuilder::addMethods()
, but this method has been deprecated.
So, currently, the simplest alternatives are to define (somewhere) a new class or to use an anonymous class, which extends the class affected by the test and implements the new method.
In my case, I extend the DropdownHelper
class by adding the (non-existent in the original) getLastLink()
method:
$Dropdown = new class (new View()) extends DropdownHelper {
public function getLastLink(): string
{
return $this->_links ? end($this->_links) : '';
}
};
Now the problem is calling
$Dropdown->getLastLink()
phpstan gives me this error:
Call to an undefined method Climat\Core\View\Helper\DropdownHelper::getLastLink().
How can I properly document this? I would like to avoid defining another class elsewhere and using the anonymous one (and I would like to avoid suppressing the error, but rather document the anonymous class correctly).
Thanks.
EDIT
I close for my mistake.
In fact, trying a simpler and stupider example:
<?php
class First {
public function methodFromTheFirstClass(): void {}
}
$Second = new class extends First {
public function methodFromTheSecondClass(): void {}
};
$Second->methodFromTheFirstClass();
$Second->methodFromTheSecondClass();
the error does not appear and is not replicable.
So, necessarily, the problem is specifically related to the single class with which I am interacting (even if, as specified, the anonymous class and the method call are on the same scope).
Thanks and sorry.
I need to run tests on a certain class, but adding a method that was not originally present.
Previously this need could be satisfied using MockBuilder::addMethods()
, but this method has been deprecated.
So, currently, the simplest alternatives are to define (somewhere) a new class or to use an anonymous class, which extends the class affected by the test and implements the new method.
In my case, I extend the DropdownHelper
class by adding the (non-existent in the original) getLastLink()
method:
$Dropdown = new class (new View()) extends DropdownHelper {
public function getLastLink(): string
{
return $this->_links ? end($this->_links) : '';
}
};
Now the problem is calling
$Dropdown->getLastLink()
phpstan gives me this error:
Call to an undefined method Climat\Core\View\Helper\DropdownHelper::getLastLink().
How can I properly document this? I would like to avoid defining another class elsewhere and using the anonymous one (and I would like to avoid suppressing the error, but rather document the anonymous class correctly).
Thanks.
EDIT
I close for my mistake.
In fact, trying a simpler and stupider example:
<?php
class First {
public function methodFromTheFirstClass(): void {}
}
$Second = new class extends First {
public function methodFromTheSecondClass(): void {}
};
$Second->methodFromTheFirstClass();
$Second->methodFromTheSecondClass();
the error does not appear and is not replicable.
So, necessarily, the problem is specifically related to the single class with which I am interacting (even if, as specified, the anonymous class and the method call are on the same scope).
Thanks and sorry.
Share Improve this question edited Jan 29 at 14:41 Mirko Pagliai asked Jan 29 at 10:06 Mirko PagliaiMirko Pagliai 1,2501 gold badge19 silver badges36 bronze badges 6 | Show 1 more comment1 Answer
Reset to default 2Best to add an interface. Let the anonymous class implement the interface and let the method returning the anonymous class typehint that interface.
addMethods()
). I can describe the concrete use case (I think it's simpler): the$_links
property is not otherwise accessible (and it's an array and I need the last value). Other alternatives would be to implement a "get" method or useReflectionProperty
. I would like to avoid modifying the original class and understand if it is possible to avoid somewhat "cumbersome" workarounds (in short, I know some solutions, I would like to understand which is the best method) – Mirko Pagliai Commented Jan 29 at 10:36$Dropdown = new class
definition in the same scope as the$Dropdown->getLastLink()
call? If it is, it feels rather like a bug/limitation in PHPStan, because it's incorrectly identified$Dropdown
as of typeDropdownHelper
, rather than as a sub-class with an extra method. If it's not, what's the type declaration of the parameter where$Dropdown
is passed - because that's what PHPStan will be analysing? – IMSoP Commented Jan 29 at 11:32