I use LARAVEL 9 and PHPSTAN
I have this simple test method :
public function createAndAuthenticatedAnUser(string $status = 'VALIDATED', bool $isAdmin = false): User
{
$user = User::factory()->create([
'status' => $status,
'is_admin' => $isAdmin
])->first();
$this->actingAs($user);
return $user;
}
When I run PHPSTAN, I have these errors :
40 Parameter #1 $user of method Illuminate\Foundation\Testing\TestCase::actingAs() expects
Illuminate\Contracts\Auth\Authenticatable, Illuminate\Database\Eloquent\Model|null given.
41 Method Tests\Feature\ValidateRegistrationTest::createAndAuthenticatedAnUser() should return App\Models\User
but returns Illuminate\Database\Eloquent\Model|null.
For the 1st error : The actingAs expects an User, it is the case.
For the 2nd error : The function returns an User (which extends Authenticatable)
What can be wrong in this code for PHPSTAN ?
Firstly don't run
PHPStan
for unit tests,PHPStan
is to check type integrity and other static analytics it can provide. They don't make sense in a unit test.Secondly your factory calls are wrong. If no count is provided,
create()
only creates a single model returns it like so. If count is higher than 1, it will return a collection.When you then call first(), it calls it on a single users query builder. That returns Model or null.
This problem is related to typehinting and is what
PHPStan
checks for, actingAs wants anAuthenticatable
which is your User class. The only thingPHPStan
knows, is your first call returns a model or null. This is not type strict, therefor it complains. As Matias pointed out, everything is solved with forcing the typehint, which are needed in many of the more generic functions ofLaravel
.