Laravel特性测试:仅调用一次外部HTTP请求

8zzbczxx  于 2023-02-05  发布在  其他
关注(0)|答案(1)|浏览(105)

我有一个登录函数,需要从单独的用户服务API调用。
登录的唯一目的是用于测试,因为我需要获取将用作我的一个中间件的参数的承载令牌。
至于测试,是否可以只通过HTTP请求调用外部api一次?如果可以,我应该把它放在哪里?
我在setUp()函数上尝试过,但似乎每次在测试类上执行测试函数时都会调用它,这使得测试变慢。

    • 编辑代码:**

测试代码:

<?php

namespace Tests\Feature\Controllers;

use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\TestSuite;
use Tests\TestCase;

class MyTest extends TestCase
{
    protected string $bearerToken;

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

        $this->bearerToken = self::getToken();
    }

    protected static function getToken()
    {
        $response = Http::post('http://auth_api/oauth/token', [
            ... 
            ...
        ]);
        
        // but assume that this request always succeed.
        if ($response->failed()) return [];

        return json_decode(json_encode($response->json()), true)['access_token'];
    }

    ...test methods here
}

我还尝试过手动标记,这样在整个测试套件中定制登录函数只会被获取一次。
如下所示:

protected static $isInitiated = false;
protected string $bearerToken;

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

    if (! self::$isInitiated) {
        $this->bearerToken = self::getToken();

        self::$isInitiated = true;
    }
}

根据这里的答案
但它让我错误地说:

$bearerToken must not be accessed before initialization

因此,根据该错误,测试方法必须在它为$bearerToken赋值之前就已经执行了。
我还尝试了public static function setUpBeforeClass()

protected static ?string $bearerToken = null;

public static function setUpBeforeClass(): void
{
    self::$bearerToken = self::getToken();
}

但它也给我错误的说法:

A facade root has not been set.

有什么办法可以做到吗?

toe95027

toe950271#

您不应该在测试中调用任何外部API,原因很简单,您正在测试您或您的团队编写的应用程序,而不是其他人
因此,您应该模拟所有外部部件,例如使用Http::fake()

Http::fake([
    // Stub a JSON response for GitHub endpoints...
    'github.com/*' => Http::response(['foo' => 'bar'], 200, $headers),
 
    // Stub a string response for Google endpoints...
    'google.com/*' => Http::response('Hello World', 200, $headers),
]);

以下是文档:https://laravel.com/docs/9.x/http-client#faking-responses
而如果你真的想调用外部API,新建一个GuzzleClient,那么你就可以做你想做的事情,但是你应该意识到那不是一个好主意。

$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.github.com/user', [
    'auth' => ['user', 'pass']
]);
echo $res->getStatusCode();
// "200"
echo $res->getHeader('content-type')[0];
// 'application/json; charset=utf8'
echo $res->getBody();
// {"type":"User"...'

相关问题