Search code examples
laravellaravel-passportlaravel-testing

laravel testing fails when testing passport oauth2 with virtual database


I'm using virtual test database for my testing. my API is working with postman. but creating problem when writing test. when I execute the test it shows a long list of error containing the following message below-

"message": "Client error: POST http://localhost/oauth/token resulted in a 401 Unauthorized response:\n{\"error\":\"invalid_client\",\"message\":\"Client authentication failed\"}

here is my route-

Route::post('/v1/create', 'API\v1\UserController@register');

here is my controller

 public function register(Request $request) 
{ 

    $validator = Validator::make($request->all(), [ 
        'name' => ['required', 'string', 'max:255'],
        'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
        'password' => ['required', 'string', 'min:6', 'confirmed'],
    ]);
    if ($validator->fails()) { 
                return response()->json(['error'=>$validator->errors()], 401);            
            }
    $input = $request->all(); 
    $input['password'] = bcrypt($input['password']); 
    $user = User::create($input); 


    $http=new Client;

    $response=$http->post(url("/oauth/token"),[
        'form_params'=>[
            'grant_type'    =>'password',
            'client_id'     =>$request->client_id,
            'client_secret' =>$request->client_secret,
            'password'      =>$request->password,
            'username'      =>$request->email,
            'scope'         =>''             
            ]
        ]);
    // return response()->json(['success'=>$response], $this->successStatus); 
    return $response;

}

and here is my test-

<?php

namespace Tests\Feature\API\v1;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\User;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use PharIo\Manifest\Email;

class UserTest extends TestCase
{
use WithFaker;
use DatabaseMigrations;
public $mockConsoleOutput = false;

/** @test */
public function a_user_can_create_user(){
$user= factory(User::class)->create(); //create user
$login=$this->actingAs($user,'api'); //user login with api

 //create password grant client
 $this->artisan('passport:client', ['--password' =>true, '--no-interaction' => true, '--redirect_uri'=>'http://localhost', '--name'=>'test client']);
 // fetch client for id and secret
 $client = \DB::table('oauth_clients')->where('password_client', 1)->first();

// dd($client->getData());


$email=$this->faker->email();
$password=$this->faker->password;
$newUser=$this->json('POST','/api/v1/create',[
    'grant_type'     =>'password',
    'client_id'     => $client->id,
    'client_secret' => $client->secret,
    'name' => $this->faker->name(),
    'email' => $email,
    'password' => $password,
    'password_confirmation' => $password,
    'remember_token' => str_random(10),
]);


// ->assertJsonStructure(['access_token', 'refresh_token']);



 dd($newUser);
 // $this->assertDatabaseHas('users',['email'=>$email]);
  // $newUser->assertJsonFragment(['token_type'=>'Bearer']);
  }


  }

please help me what am I missing


Solution

  • I've solved it by proxying the request. it was happening because- when I was calling the "oauth/token" endpoint with guzzle- that call was treated as real call and test was not working there. so this helped me a lot to solve the problem.

    $tokenRequest = Request::create('oauth/token', 'POST',$request->toArray()); 
    $response = Route::dispatch($tokenRequest);