Skip to content

Commit 4b7aa41

Browse files
authored
Add test for NoDocumentMockingRule and skip interface/abstract classes (#261)
* add test * add test * Add test for NoDocumentMockingRule and skip interface/abstract classes
1 parent 4cfd04b commit 4b7aa41

File tree

7 files changed

+143
-2
lines changed

7 files changed

+143
-2
lines changed

src/Rules/Doctrine/NoDocumentMockingRule.php

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,26 @@
77
use PhpParser\Node;
88
use PhpParser\Node\Expr\MethodCall;
99
use PHPStan\Analyser\Scope;
10+
use PHPStan\Reflection\ReflectionProvider;
1011
use PHPStan\Rules\Rule;
1112
use PHPStan\Rules\RuleErrorBuilder;
13+
use PHPStan\Type\Constant\ConstantStringType;
1214
use Symplify\PHPStanRules\Enum\RuleIdentifier\PHPUnitRuleIdentifier;
1315
use Symplify\PHPStanRules\Helper\NamingHelper;
1416

1517
/**
1618
* @implements Rule<MethodCall>
19+
* @see \Symplify\PHPStanRules\Tests\Rules\Doctrine\NoDocumentMockingRule\NoDocumentMockingRuleTest
1720
*/
18-
final class NoDocumentMockingRule implements Rule
21+
final readonly class NoDocumentMockingRule implements Rule
1922
{
2023
public const string ERROR_MESSAGE = 'Instead of document mocking, create object directly to get better type support';
2124

25+
public function __construct(
26+
private ReflectionProvider $reflectionProvider
27+
) {
28+
}
29+
2230
public function getNodeType(): string
2331
{
2432
return MethodCall::class;
@@ -40,7 +48,11 @@ public function processNode(Node $node, Scope $scope): array
4048
$firstArg = $node->getArgs()[0];
4149
$mockedClassType = $scope->getType($firstArg->value);
4250
foreach ($mockedClassType->getConstantStrings() as $constantStringType) {
43-
if (! str_contains($constantStringType->getValue(), '\\Document\\')) {
51+
if (! str_contains($constantStringType->getValue(), '\\Document\\') && ! str_contains($constantStringType->getValue(), '\\Entity\\')) {
52+
continue;
53+
}
54+
55+
if ($this->shouldSkipDocumentClass($constantStringType)) {
4456
continue;
4557
}
4658

@@ -53,4 +65,20 @@ public function processNode(Node $node, Scope $scope): array
5365

5466
return [];
5567
}
68+
69+
private function shouldSkipDocumentClass(ConstantStringType $constantStringType): bool
70+
{
71+
if ($this->reflectionProvider->hasClass($constantStringType->getValue())) {
72+
$classReflection = $this->reflectionProvider->getClass($constantStringType->getValue());
73+
if ($classReflection->isAbstract()) {
74+
return true;
75+
}
76+
77+
if ($classReflection->isInterface()) {
78+
return true;
79+
}
80+
}
81+
82+
return false;
83+
}
5684
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Symplify\PHPStanRules\Tests\Rules\Doctrine\NoDocumentMockingRule\Fixture;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Symplify\PHPStanRules\Tests\Rules\Doctrine\NoDocumentMockingRule\Source\Entity\AbstractSomeEntity;
9+
use Symplify\PHPStanRules\Tests\Rules\Doctrine\NoDocumentMockingRule\Source\Entity\SomeEntity;
10+
11+
final class SomeAbstractEntityMocking extends TestCase
12+
{
13+
public function test()
14+
{
15+
$someMock = $this->createMock(AbstractSomeEntity::class);
16+
}
17+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Symplify\PHPStanRules\Tests\Rules\Doctrine\NoDocumentMockingRule\Fixture;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Symplify\PHPStanRules\Tests\Rules\Doctrine\NoDocumentMockingRule\Source\Entity\SomeEntity;
9+
10+
final class SomeEntityMocking extends TestCase
11+
{
12+
public function test()
13+
{
14+
$someMock = $this->createMock(SomeEntity::class);
15+
}
16+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Symplify\PHPStanRules\Tests\Rules\Doctrine\NoDocumentMockingRule;
6+
7+
use Iterator;
8+
use Override;
9+
use PHPStan\Rules\Rule;
10+
use PHPStan\Testing\RuleTestCase;
11+
use PHPUnit\Framework\Attributes\DataProvider;
12+
use Symplify\PHPStanRules\Rules\Doctrine\NoDocumentMockingRule;
13+
14+
final class NoDocumentMockingRuleTest extends RuleTestCase
15+
{
16+
/**
17+
* @param array<int, array<string|int>> $expectedErrorMessagesWithLines
18+
*/
19+
#[DataProvider('provideData')]
20+
public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void
21+
{
22+
$this->analyse([$filePath], $expectedErrorMessagesWithLines);
23+
}
24+
25+
/**
26+
* @return Iterator<array<array<int, mixed>, mixed>>
27+
*/
28+
public static function provideData(): Iterator
29+
{
30+
yield [__DIR__ . '/Fixture/SomeEntityMocking.php', [[
31+
NoDocumentMockingRule::ERROR_MESSAGE,
32+
14,
33+
]]];
34+
35+
yield [__DIR__ . '/Fixture/SomeAbstractEntityMocking.php', []];
36+
}
37+
38+
/**
39+
* @return string[]
40+
*/
41+
#[Override]
42+
public static function getAdditionalConfigFiles(): array
43+
{
44+
return [__DIR__ . '/config/configured_rule.neon'];
45+
}
46+
47+
protected function getRule(): Rule
48+
{
49+
return self::getContainer()->getByType(NoDocumentMockingRule::class);
50+
}
51+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Symplify\PHPStanRules\Tests\Rules\Doctrine\NoDocumentMockingRule\Source\Entity;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
7+
/**
8+
* @ORM\Entity()
9+
*/
10+
abstract class AbstractSomeEntity
11+
{
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Symplify\PHPStanRules\Tests\Rules\Doctrine\NoDocumentMockingRule\Source\Entity;
4+
5+
use Doctrine\ORM\Mapping as ORM;
6+
7+
/**
8+
* @ORM\Entity()
9+
*/
10+
class SomeEntity
11+
{
12+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
includes:
2+
- ../../../../config/included_services.neon
3+
4+
rules:
5+
- Symplify\PHPStanRules\Rules\Doctrine\NoDocumentMockingRule

0 commit comments

Comments
 (0)