Skip to content

Commit 88d4efc

Browse files
mhujerondrejmirtes
authored andcommitted
AssertSameNullExpectedRule
1 parent 967356e commit 88d4efc

File tree

5 files changed

+112
-0
lines changed

5 files changed

+112
-0
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ It also contains this framework-specific rule (can be enabled separately):
1818

1919
* Check that both values passed to `assertSame()` method are of the same type.
2020

21+
It also contains this strict framework-specific rule (can be enabled separately):
22+
23+
* Check that you are not using `assertSame()` with `null` as expected value. `assertNull()` should be used instead.
24+
2125
## How to document mock objects in phpDocs?
2226

2327
If you need to configure the mock even after you assign it to a property or return it from a method, you should add `PHPUnit_Framework_MockObject_MockObject` to the phpDoc:
@@ -81,3 +85,9 @@ To perform framework-specific checks, include also this file:
8185
```
8286
- vendor/phpstan/phpstan-phpunit/rules.neon
8387
```
88+
89+
To perform addition strict PHPUnit checks, include also this file:
90+
91+
```
92+
- vendor/phpstan/phpstan-phpunit/strictRules.neon
93+
```
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\PHPUnit;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Type\NullType;
8+
9+
class AssertSameNullExpectedRule implements \PHPStan\Rules\Rule
10+
{
11+
12+
public function getNodeType(): string
13+
{
14+
return \PhpParser\NodeAbstract::class;
15+
}
16+
17+
/**
18+
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $node
19+
* @param \PHPStan\Analyser\Scope $scope
20+
* @return string[] errors
21+
*/
22+
public function processNode(Node $node, Scope $scope): array
23+
{
24+
if (!AssertRuleHelper::isMethodOrStaticCallOnTestCase($node, $scope)) {
25+
return [];
26+
}
27+
28+
if (count($node->args) < 2) {
29+
return [];
30+
}
31+
if (!is_string($node->name) || strtolower($node->name) !== 'assertsame') {
32+
return [];
33+
}
34+
35+
$leftType = $scope->getType($node->args[0]->value);
36+
37+
if ($leftType instanceof NullType) {
38+
return [
39+
'You should use assertNull() instead of assertSame(null, $actual).',
40+
];
41+
}
42+
43+
return [];
44+
}
45+
46+
}

strictRules.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
services:
2+
-
3+
class: PHPStan\Rules\PHPUnit\AssertSameNullExpectedRule
4+
tags:
5+
- phpstan.rules.rule
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\PHPUnit;
4+
5+
use PHPStan\Rules\Rule;
6+
7+
class AssertSameNullExpectedRuleTest extends \PHPStan\Testing\RuleTestCase
8+
{
9+
10+
protected function getRule(): Rule
11+
{
12+
return new AssertSameNullExpectedRule();
13+
}
14+
15+
public function testRule()
16+
{
17+
$this->analyse([__DIR__ . '/data/assert-same-null-expected.php'], [
18+
[
19+
'You should use assertNull() instead of assertSame(null, $actual).',
20+
10,
21+
],
22+
[
23+
'You should use assertNull() instead of assertSame(null, $actual).',
24+
13,
25+
],
26+
]);
27+
}
28+
29+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace ExampleTestCase;
4+
5+
class AssertSameNullExpectedTestCase extends \PHPUnit\Framework\TestCase
6+
{
7+
8+
public function testAssertSameWithNullAsExpected()
9+
{
10+
$this->assertSame(null, 'a');
11+
12+
$a = null;
13+
$this->assertSame($a, 'b');
14+
15+
$this->assertSame('a', 'b'); // OK
16+
17+
/** @var string|null $c */
18+
$c = null;
19+
$this->assertSame($c, 'foo'); // nullable is OK
20+
}
21+
22+
}

0 commit comments

Comments
 (0)