我正在尝试创建一个功能测试来测试获取 OAuth 访问 token 。使用 Postman 时,一切都运行良好(实际代码),因此我确信在我的测试代码中我没有正确实现设置。
过去,我运行 artisan 命令,然后将 client_secret
复制/粘贴到我的 .env
文件中。因为我使用的是 CI/CD,所以我不能这样做。我需要:
- 创建一个 artisan 命令来附加
.env
- 从
oauth_clients
表中读取 secret (似乎是最简单的途径)
我关注了this SO thread帮助到达我所在的位置,但无法使其发挥作用。
这是我的测试:
MyFeatureTest.php
use RefreshDatabase, WithFaker, DatabaseMigrations;
public function setUp(): void
{
parent::setUp();
$this->artisan('passport:install');
}
public function a_user_can_get_a_token()
{
$credentials = [
'username' => 'username',
'password' => 'password',
];
$http = $this->postJson('api/v1/login', $credentials);
$response = json_decode($http->getContent());
// dd($response);
$http->assertStatus(200)
->assertJsonStructure([
'token_type', 'expires_in', 'access_token', 'refresh_token',
])
->assertJson([
'token_type' => $response->token_type,
'expires_in' => $response->expires_in,
'access_token' => $response->access_token,
'refresh_token' => $response->refresh_token,
]);
在我处理登录
路由的 Controller 中:
public function __construct()
{
$this->client = DB::table('oauth_clients')
->where('id', 2)
->first();
}
...
public function getOauthAccessToken($credentials)
{
$response = Http::asForm()->post(env('APP_URL') . '/oauth/token', [
'grant_type' => 'password',
'client_id' => $this->client->id,
'client_secret' => $this->client->secret,
'username' => $credentials['username'],
'password' => $credentials['password'],
'scope' => '*',
]);
if ($response->successful()) {
return $response->json();
} else {
dd($response->body());
}
}
当使用 postman 测试我的路线/ Controller 时,一切都很好。我按预期得到了 Barer 代币。
当我运行功能测试时,我的 Controller 返回 null
。
为了排除故障,我尝试了上面的 dd($response->body()) 。这是我得到的:
"{"error":"invalid_client","error_description":"Client authentication failed","message":"Client authentication failed"}"
如果我dd($this->client->secret)
,我就能看到 key 。这非常令人困惑,因为看起来一切正常......
如何正确设置我的测试,以便在我进行登录测试时护照已准备好/配置?感谢您的任何建议!
最佳答案
谢谢大家的建议!
这就是最终对我有用的东西。由于我是 api 的唯一使用者,因此我不需要返回整个 /oauth/token
响应(尽管它将来可能会有所帮助)。
MyTest.php
use RefreshDatabase, WithFaker, DatabaseMigrations;
public function setUp(): void
{
parent::setUp();
$this->artisan('passport:install', ['--no-interaction' => true,]);
}
/** @test */
public function a_user_can_authenticate_using_email()
{
$credentials = [
'username' => '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="512534222511343c30383d7f323e3c" rel="noreferrer noopener nofollow">[email protected]</a>',
'password' => 'password',
];
$http = $this->postJson('api/v1/login', $credentials)
->assertStatus(200);
}
MyController.php
// authenticate the $credentials to get a $user object.
...
return $this->getOauthAccessToken($user);
...
private function getOauthAccessToken($user)
{
$token = $user->createToken('My Personal Access Token')->accessToken;
return response()->json($token);
}
我只是验证我是否收到了 200 响应,而不是验证返回的确切 json(这是理想的)。因为我的身份验证有点麻烦(检查多个数据库),所以确保我通过 200 完成所有操作非常重要。
希望这对某人有帮助!
关于Laravel 护照 : How can I properly setup a feature test?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62663597/