Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Jacko's avatar
Level 4

Passport - Personal Access Token Unit Test

Can someone help me to put up a unit test for personal access tokens? This test should validate, that Passport is setup correct and a new valid token can be created for a new user.

    /**
     *@test
     */
    public function Create_an_access_token()
    {
        $user = factory(User::class)->create();

        $token = $user->createToken('TestToken')->accessToken;

        $header = [];
        $header['Accept'] = 'application/json';
        $header['Authorization'] = 'Bearer '.$token;

        $this->json('GET', '/api/user', [], $header)
                 ->seeJson([
                 'id' => $user->id,
                 'email' => $user->email,
                 'name' => $user->name,
        ]);
    }

This test is running on the in-memory sqlite test db connection. However I always get an ErrorException of Trying to get property of non-object:

...\vendor\laravel\passport\src\ClientRepository.php:66
...\vendor\laravel\passport\src\PersonalAccessTokenFactory.php:71
...\vendor\laravel\passport\src\HasApiTokens.php:68
...\tests\ApiAuthenticationTest.php:19

Seems like there is no personal access token client available. The documentation says, that I should run php artisan passport:client --personal but how can this be done in a unit test?

0 likes
8 replies
Jacko's avatar
Jacko
OP
Best Answer
Level 4

I got it working by extracting the code for client generation from the passport command and adding it to the test:

        $clientRepository = new ClientRepository();
        $client = $clientRepository->createPersonalAccessClient(
            null, 'Test Personal Access Client', 'http://localhost'
        );

        DB::table('oauth_personal_access_clients')->insert([
            'client_id' => $client->id,
            'created_at' => new DateTime,
            'updated_at' => new DateTime,
        ]);

This creates an access client and stores it in the database. Since I am using in-memory sqlite for unit tests, this needs to be done every time the unit test is executed.

4 likes
jeffsee.55@gmail.com's avatar

If you're testing a controller and are extending TestCase you can use the built in 'actingAs' method

/** @test */
public function it_gets_the_unit()
{
    $user = factory(App\User::class)->create();
    $this->actingAs($user, 'api');
    
    $unitCode = '1234';
    
    $this->json('GET', '/api/units/' . $unitCode)
        ->seeJsonContains(['id' => $unitCode]);
}
8 likes
egjw's avatar

Another way to prevent copy/paste source code is to just call artisan command in the setup method .

public function setUp() {
        parent::setUp();
        $this->artisan('passport:install');
}

This will ensure the passport client are generated for testing purpose.

8 likes

Please or to participate in this conversation.