0

由于我的项目已经部署了多个域名,所以需要测试的API接口是使用api.example.test域名作为入口。

使用$this->get('/v1/ping')in Feature Test 会请求到www.example.test,我希望在in 中$this->withHeader('Host', config('domain.api_domain'))统一设置自动请求 API 相关的测试到Go in。setUpApiFeatureBaseTestCaseapi.example.test

但是,在实践中,我发现这是无效的。通过跟踪代码,我发现了两个可能导致无效Host设置的代码:

第一名(Laravel):

Laravel 框架中的代码src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:503$uri ='/v1/ping' ,传入参数$this->prepareUrlForRequest($uri),得到一个完整的 Url,默认 Host,返回值为http://www.example.test/v1/ping.

第二名(Symfony):

在 Symfony HttpFoundation 组件Request.php:355$uri的代码中,会先使用解析进来host的,然后默认覆盖在 Header 中Host

以上两个代码最终导致了HostI set bywithHeader失败。显然,在这段代码逻辑中,不能认为 Symfony HttpFoundation Component 选择 Host in conflict 是错误的,但是我提交这个问题issue给 Laravel Framework 时就关闭了。

我不知道这个问题是abug还是feature

最后,很抱歉我的问题打断了大家的时间,但是如果对这个问题有结论,请告诉我应该怎样更合适?

我目前的做法是$this->get($this->api_base_url . '/v1/ping'),但我不认为这是elegant

3Q!!1

代码示例

// File: config/domain.php
return [
    'api_domain' => 'api.example.test',
    'web_domain' => 'www.example.test',
];

// File: routes/demo.php
Route::domain(config('domain.api_domain'))
     ->middleware(['auth:api', 'api.sign.check'])
     ->namespace($this->namespace)
     ->group(function () {
         Route::get('/v1/ping', function () {
             return 'This Api v1';
         });
     });

Route::domain(config('domain.web_domain'))
     ->middleware('web')
     ->namespace($this->namespace)
     ->group(base_path('routes/web.php'));

// File: tests/ApiFeatureBaseTestCase.php
namespace Tests;

class ApiFeatureBaseTestCase extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        $this->withHeader('Host', config('domain.api_domain'));
    }
}

// File: tests/Feature/ApiPingTest.php
namespace Tests\Feature;

use Tests\ApiFeatureBaseTestCase;


class ApiPingTest extends ApiFeatureBaseTestCase
{
    public function testPing()
    {
       $this->get('/v1/ping');
    }
}
4

1 回答 1

0

你能在你的ApiFeatureBaseTestCase类上创建一个包装方法吗?

public function get($uri, array $headers = [])
{
    return parent::get(config('domain.api_domain') . $uri, $headers);
}

然后在你的ApiPingTest课上:

public function testPing()
{
    $this->get('/v1/ping');
}
于 2020-11-23T07:21:18.410 回答