-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question: what the reason for existing SingleMockPropertyTypeRector? #419
Comments
Thanks for this question. The reason is the main identity in code. See https://tomasvotruba.com/blog/5-ways-to-extract-value-from-overmocked-tests section 4 |
By using intersection types, I can help IDE / static analysis with type inference. When passing this property to a function that requires the original type, it ensures safety and correctness. Here is a full example: <?php
declare(strict_types=1);
namespace GitHubExample\Tests;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
final class ResultStatusDeprecatedRectorTest extends TestCase
{
// rector will change this to `private MockObject $foobar;`
private SomeObject&MockObject $foobar;
protected function setUp(): void
{
$b = $this->getMockBuilder(SomeObject::class);
$b
->enableOriginalConstructor()
->onlyMethods(['someMethod']);
$this->foobar = $b->getMock();
parent::setUp();
}
public function testSuccess(): void
{
$this->foobar->expects($this->once())->method('someMethod')->willReturn(59);
$toTest = new class($this->foobar) {
public function __construct(private readonly SomeObject $inner)
{
}
public function someFacadeMethod(): int
{
$this->inner->changeState();
return $this->inner->someMethod();
}
};
$this->assertSame(59, $toTest->someFacadeMethod());
$this->assertTrue($this->foobar->getState());
}
}
class SomeObject
{
private bool $state = false;
public function changeState(): void
{
$this->state = true;
}
public function getState(): bool
{
return $this->state;
}
public function someMethod(): int
{
return 42;
}
} I believe the recommended code quality rule should enforce the use of intersection types rather than union types or just a MockObject. What is your opinion on changing the recommended rule behavior for this use case? |
If both types are allowed, mock and real object can be assigned. Mock overridden to object, then overridden to object. What a mess. This was code smell in few projects, this rule will prevent it. Also, IDE autocompletes real methods on mocked objects later in the code, giving a false positive hint that its a real object. This rule prevents it. Feel free to exclude it via skip(), if it doesn't feel a good fit for you 👍 |
Ok, thanks. I meant two separated methods (one for mock, one for real type). |
https://getrector.com/rule-detail/single-mock-property-type-rector
Could you tell me what the reason is for introducing such a rule?
As I see in the code of the rule - it will refactor this:
To this:
Using the intersection type for such a use case is super clear, in my opinion, and this should not be refactored to mention only
MockObject
.Introduced in #401
The text was updated successfully, but these errors were encountered: