Skip to content

Commit 89d9d9f

Browse files
committed
Added DataProviderDataRuleTest
1 parent dc0fb57 commit 89d9d9f

File tree

4 files changed

+113
-15
lines changed

4 files changed

+113
-15
lines changed

src/Rules/PHPUnit/DataProviderDataRule.php

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use PhpParser\Node;
77
use PHPStan\Analyser\Scope;
88
use PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection;
9+
use PHPStan\Reflection\ReflectionProvider;
910
use PHPStan\Rules\Rule;
1011
use PHPUnit\Framework\TestCase;
1112

@@ -14,6 +15,15 @@
1415
*/
1516
class DataProviderDataRule implements Rule
1617
{
18+
private ReflectionProvider $reflectionProvider;
19+
20+
public function __construct(
21+
ReflectionProvider $reflectionProvider,
22+
)
23+
{
24+
$this->reflectionProvider = $reflectionProvider;
25+
}
26+
1727
public function getNodeType(): string
1828
{
1929
return Node\Stmt\Return_::class;
@@ -40,27 +50,29 @@ public function processNode(Node $node, Scope $scope): array
4050

4151
$classReflection = $scope->getClassReflection();
4252

43-
if ($classReflection === null || !$classReflection->is(TestCase::class)) {
53+
if (
54+
$classReflection === null
55+
|| !$classReflection->is(TestCase::class)
56+
|| $classReflection->isAbstract()
57+
) {
4458
return [];
4559
}
4660

4761
// XXX check whether the method is used as a data provider
4862

49-
if (method_exists($scope, 'invokeNodeCallback')) {
50-
foreach($node->expr->items as $item) {
51-
if (!$item->value instanceof Node\Expr\Array_) {
52-
return [];
53-
}
54-
55-
$args = $this->arrayItemsToArgs($item->value);
56-
$var = new Node\Expr\New_(new Node\Name('test'));
57-
$scope->invokeNodeCallback(new Node\Expr\MethodCall(
58-
$var,
59-
'testTrim',
60-
$args,
61-
['startLine' => $item->getStartLine()]
62-
));
63+
foreach($node->expr->items as $item) {
64+
if (!$item->value instanceof Node\Expr\Array_) {
65+
return [];
6366
}
67+
68+
$args = $this->arrayItemsToArgs($item->value);
69+
$var = new Node\Expr\New_(new Node\Name($classReflection->getName()));
70+
$scope->invokeNodeCallback(new Node\Expr\MethodCall(
71+
$var,
72+
'testTrim',
73+
$args,
74+
['startLine' => $item->getStartLine()]
75+
));
6476
}
6577

6678
return [];
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Rules\PHPUnit;
4+
5+
use PHPStan\Rules\PHPUnit\DataProviderDataRule;
6+
use PHPStan\Rules\Rule;
7+
use PHPStan\Testing\RuleTestCase;
8+
9+
/**
10+
* @extends RuleTestCase<DataProviderDataRule>
11+
*/
12+
class DataProviderDataRuleTest extends RuleTestCase
13+
{
14+
15+
protected function getRule(): Rule
16+
{
17+
$reflection = $this->createReflectionProvider();
18+
19+
return new DataProviderDataRule(
20+
$reflection
21+
);
22+
}
23+
24+
public function testRule(): void
25+
{
26+
$this->analyse([__DIR__ . '/data/data-provider-data.php'], [
27+
[
28+
'Parameter #2 $input of method test::testTrim() expects string, int given.',
29+
25,
30+
],
31+
[
32+
'Parameter #2 $input of method test::testTrim() expects string, false given.',
33+
29,
34+
],
35+
]);
36+
}
37+
38+
/**
39+
* @return string[]
40+
*/
41+
public static function getAdditionalConfigFiles(): array
42+
{
43+
return [
44+
__DIR__ . '/data-provider-data.neon',
45+
];
46+
}
47+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
includes:
2+
- ../../../extension.neon
3+
4+
rules:
5+
- PHPStan\Rules\Methods\CallMethodsRule
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace DataProviderDataTest;
4+
5+
use PHPUnit\Framework\Attributes\DataProvider;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class FooTest extends TestCase
9+
{
10+
11+
#[DataProvider('aProvider')]
12+
public function testTrim(string $expectedResult, string $input): void
13+
{
14+
}
15+
16+
public function aProvider(): array /** @phpstan-ignore missingType.iterableValue */
17+
{
18+
return [
19+
[
20+
'Hello World',
21+
" Hello World \n",
22+
],
23+
[
24+
'Hello World',
25+
123,
26+
],
27+
[
28+
'Hello World',
29+
false,
30+
],
31+
];
32+
}
33+
}
34+

0 commit comments

Comments
 (0)