首页 > 解决方案 > how do I best unit test Passport in a CI/CD pipeline?

问题描述

So I'm trying to write some unit/feature tests for an implementation of Passport on Lumen for our new authentication server. However I'm running into so many annoying issues I'm not even sure I'm going about doing this the right way.

The way passport is currently set up in Lumen, for web requests especially, we fake internal requests to Passport and store the client id and secret in an env file on the backend. (The client secret is hardcoded in .env so it will always be created with the same ID and secret via seeder on each dev machine) Here is the code for that:

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));
    }
}

Anyways, this class works great in our dev environment. It handles requests and hands out a access token / refresh token like it's supposed to.

However, when I run unit tests testing out this class, I keep getting the error "grant type not supported," despite the password client existing in the unit test db and all the environment variables being present.

Thus, I have switched to instead of testing out the PassportOauth class, to using $this->call() in unit tests for faking calls to 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());
}

this works great on development! Unit tests pass and everything. However, when they run in our ci/cd pipeline and it runs unit tests, I get the error that the oauth public/private keys are not installed. This is pretty obvious, I just need to run passport:install right?

Problem is, the passport db tables aren't created in the pipeline at that moment. And I'm not sure I want to add creating the db migrations each time a ci/cd pipeline is run.

So my questions here are:

1) Am I even approaching this the right way? If I am, how do I get around the oauth private/public keys that I don't even need, because I've statically created the password client from hardcoded values in my env file?

2) Is there a better approach to unit testing this? So far my approach has given me a lot of grief.

标签: phpunit-testingoauthlumenlaravel-passport

解决方案


是的,测试它的方法是不尝试对其进行单元测试。你想要的是集成测试。

您将直接调用身份验证服务器,就像普通客户端一样,您将获得一个令牌,然后您开始进行其他测试,当令牌正常时会发生什么,当它过期时会发生什么,当您拥有错误的令牌时会发生什么你的资源服务器等


推荐阅读