如何在 CI/CD 管道中对 Passport 进行最佳单元测试?
how do I best unit test Passport in a CI/CD pipeline?
所以我正在尝试编写一些 unit/feature 测试,以便为我们的新身份验证服务器在 Lumen 上实施 Passport。然而,我 运行 遇到了很多烦人的问题,我什至不确定我是否会以正确的方式来做这件事。
目前在 Lumen 中设置 passport 的方式,尤其是对于网络请求,我们伪造对 Passport 的内部请求,并将客户端 id 和密码存储在后端的 env 文件中。 (客户端密码被硬编码在 .env 中,所以它总是通过每台开发机器上的播种器使用相同的 ID 和密码创建)下面是代码:
class PassportOauth
{
const OAUTH_LOGIN = '/api/v1/oauth/token';
/**
* Functions to encapsulate the token request (login) needs
* */
public static function login($username, $password)
{
return self::clientLogin($username, $password, env('CLIENT_ID'), env('CLIENT_SECRET'));
}
public static function clientLogin($username, $password, $clientID, $clientSecret)
{
return self::post(self::OAUTH_LOGIN, [
'grant_type' => 'password',
'client_id' => $clientID,
'client_secret' => $clientSecret,
'username' => $username,
'password' => $password
]);
}
private static function post($url, $data)
{
return app()->handle(Request::create($url, 'POST', $data));
}
}
无论如何,这个 class 在我们的开发环境中很好。它处理请求并像预期的那样分发访问令牌/刷新令牌。
但是,当我 运行 单元测试测试这个 class 时,尽管单元测试数据库和所有环境变量中存在密码客户端,但我仍然收到错误 "grant type not supported,"在场。
因此,我没有测试 PassportOauth class,而是在单元测试中使用 $this->call()
来伪造对 Passport 的调用:
private function doLogin($email, $password)
{
return json_decode($this->call('POST', self::OAUTH_LOGIN, [
'grant_type' => 'password',
'client_id' => env('CLIENT_ID'),
'client_secret' => env('CLIENT_SECRET'),
'username' => $email,
'password' => $password
])->getContent());
}
这对开发很有帮助!单元测试通过了一切。但是,当它们在我们的 ci/cd 管道中 运行 并且它 运行 进行单元测试时,我收到错误消息,即未安装 oauth public/private 密钥。这很明显,我只需要 运行 passport:install
对吧?
问题是,此时没有在管道中创建护照数据库表。而且我不确定是否要在每次 ci/cd 管道为 运行.
时添加创建数据库迁移
所以我的问题是:
1) 我的处理方式是否正确?如果我是,我如何绕过我什至不需要的 oauth private/public 密钥,因为我已经从我的 env 文件中的硬编码值静态创建了密码客户端?
2) 是否有更好的单元测试方法?到目前为止,我的做法让我很伤心。
是的,测试它的方法是不尝试对其进行单元测试。你要的是集成测试。
你会直接调用认证服务器,就像一个普通的客户端,你会得到一个令牌然后你开始做其他测试,当令牌没问题时会发生什么,当它过期时会发生什么,当你您的资源服务器等的令牌有误
所以我正在尝试编写一些 unit/feature 测试,以便为我们的新身份验证服务器在 Lumen 上实施 Passport。然而,我 运行 遇到了很多烦人的问题,我什至不确定我是否会以正确的方式来做这件事。
目前在 Lumen 中设置 passport 的方式,尤其是对于网络请求,我们伪造对 Passport 的内部请求,并将客户端 id 和密码存储在后端的 env 文件中。 (客户端密码被硬编码在 .env 中,所以它总是通过每台开发机器上的播种器使用相同的 ID 和密码创建)下面是代码:
class PassportOauth
{
const OAUTH_LOGIN = '/api/v1/oauth/token';
/**
* Functions to encapsulate the token request (login) needs
* */
public static function login($username, $password)
{
return self::clientLogin($username, $password, env('CLIENT_ID'), env('CLIENT_SECRET'));
}
public static function clientLogin($username, $password, $clientID, $clientSecret)
{
return self::post(self::OAUTH_LOGIN, [
'grant_type' => 'password',
'client_id' => $clientID,
'client_secret' => $clientSecret,
'username' => $username,
'password' => $password
]);
}
private static function post($url, $data)
{
return app()->handle(Request::create($url, 'POST', $data));
}
}
无论如何,这个 class 在我们的开发环境中很好。它处理请求并像预期的那样分发访问令牌/刷新令牌。
但是,当我 运行 单元测试测试这个 class 时,尽管单元测试数据库和所有环境变量中存在密码客户端,但我仍然收到错误 "grant type not supported,"在场。
因此,我没有测试 PassportOauth class,而是在单元测试中使用 $this->call()
来伪造对 Passport 的调用:
private function doLogin($email, $password)
{
return json_decode($this->call('POST', self::OAUTH_LOGIN, [
'grant_type' => 'password',
'client_id' => env('CLIENT_ID'),
'client_secret' => env('CLIENT_SECRET'),
'username' => $email,
'password' => $password
])->getContent());
}
这对开发很有帮助!单元测试通过了一切。但是,当它们在我们的 ci/cd 管道中 运行 并且它 运行 进行单元测试时,我收到错误消息,即未安装 oauth public/private 密钥。这很明显,我只需要 运行 passport:install
对吧?
问题是,此时没有在管道中创建护照数据库表。而且我不确定是否要在每次 ci/cd 管道为 运行.
时添加创建数据库迁移所以我的问题是:
1) 我的处理方式是否正确?如果我是,我如何绕过我什至不需要的 oauth private/public 密钥,因为我已经从我的 env 文件中的硬编码值静态创建了密码客户端?
2) 是否有更好的单元测试方法?到目前为止,我的做法让我很伤心。
是的,测试它的方法是不尝试对其进行单元测试。你要的是集成测试。
你会直接调用认证服务器,就像一个普通的客户端,你会得到一个令牌然后你开始做其他测试,当令牌没问题时会发生什么,当它过期时会发生什么,当你您的资源服务器等的令牌有误