0

I'm testing api endpoint which is authenticated with laravel passport. I'm writing a feature test for checking if oauth/token can return a valid access_token. It is working fine in postman but I am using a different database for testing so when I run the test I'm always getting 400 error. Though I'm able to test all authenticated routes but I'm stuck when I want to test api/login or oauth/token endpoints. I'm running artisan command to install passport for test database. How to get client id and secret?

In TestCase class

public function setUp(): void
    {
        parent::setUp();

        Artisan::call('migrate', ['-vvv' => true]);
        Artisan::call('passport:install', ['-vvv' => true]);
        Artisan::call('db:seed', ['-vvv' => true]);
    }

LoginTest class

public function test_it_returns_a_valid_token_if_credentials_do_match()
    {
        $client = Passport::client();

        $user = User::factory()->create([
            'email' => $email = 'test@test.com',
            'password' => $password = '12345678'
        ]);

        $body = [
            'client_id' => $client->id,
            'client_secret' => $client->secret,
            'username' => $email,
            'password' => $password
        ];

        $this->json('POST', '/oauth/token', $body)
            ->assertStatus(200);
    }

Here $client = Passport::client() return null. I didn't find any solution to get oauth client credentials.

Niloy Quazi
  • 107
  • 2
  • 12
  • The passport oauth is already tested by their developer and it works fine, why do you need to test if it can generate token correctly? – Mohsen Nazari Jul 15 '21 at 20:49
  • Cause I'm using TDD approach for development. TDD helps avoid errors and bugs when introducing new features in an application. – Niloy Quazi Jul 15 '21 at 21:08
  • What I mean is that, if you had written a login endpoint yourself, writing test for that would be very wise, but since you are writing a test for a library endpoint which already is heavily tested, what is the necessity? – Mohsen Nazari Jul 15 '21 at 21:11
  • Look at this, you are trying to write the same test, https://github.com/laravel/passport/blob/10.x/tests/Feature/AccessTokenControllerTest.php#L44 – Mohsen Nazari Jul 15 '21 at 21:13
  • Yes, but I have created custom route "api/login" for login which using this passport default route. My target is to test "api/login" route. Thanks a lot for sharing this link I have found solution. – Niloy Quazi Jul 15 '21 at 21:29
  • Also for testing authenticated users, use passport mock, it is way easier than handling actual token. You can find it here https://laravel.com/docs/8.x/passport#testing – Mohsen Nazari Jul 15 '21 at 21:46
  • Thanks, I'm already using this for testing authenticated routes. – Niloy Quazi Jul 15 '21 at 21:58
  • Now I'm facing a new problem for testing login route "api/login". In AuthController login method I passed client credentials form .env file. But client credentials are different for testing database, so I passed new credentials for this, but it can not override .env files values. – Niloy Quazi Jul 15 '21 at 22:05
  • Try this inside your test, https://www.php.net/manual/en/function.putenv.php – Mohsen Nazari Jul 15 '21 at 22:09
  • Now, after overriding .env file values I'm getting 401 error, before I got 400 error. – Niloy Quazi Jul 15 '21 at 23:20
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/234948/discussion-between-niloy-quazi-and-mohsen-nazari). – Niloy Quazi Jul 16 '21 at 04:41

1 Answers1

2

Actually $client = Passport::client(); doesn't return client. I have found a solution to create client from LoginTest.

$user = User::factory()->create([
            'email' => $email = 'test@test.com',
            'password' => $password = '12345678'
        ]);

$client = ClientFactory::new()->asPasswordClient()->create(['user_id' => $user->id]);

        $response = $this->json(
            'POST', '/oauth/token',
            [
                'grant_type' => 'password',
                'client_id' => $client->id,
                'client_secret' => $client->secret,
                'username' => $user->email,
                'password' => $password,
            ]
        )
        ->assertStatus(200);
Niloy Quazi
  • 107
  • 2
  • 12