Laravel:如何编写路由宏、中间件和模型绑定的测试

jxct1oxe  于 2022-12-30  发布在  其他
关注(0)|答案(1)|浏览(119)

我构建了一个简单的方法来标识租户与子域,例如:user1.example.com,租户将是user1,另一方面,如果user1不存在,user1.example.com将响应404
我在服务提供者中定义了一个Macro,如下所示:

/**
 * Register services.
 *
 * @return void
 */
public function register()
{
    $this->app->singleton('tenancy', function (Application $app) {
        return new TenancyMananger($app);
    });
}

/**
 * Bootstrap services.
 *
 * @return void
 */
public function boot()
{
    Route::macro('tenancy', fn (Closure $groups) => Route::domain(sprintf('{tenant}.example.com'))
        ->middleware(['tenancy'])
        ->group($groups));

    Route::model('tenant', Tenant::class);
}

然后,使用middleware初始化并标识租户:

public function handle(Request $request, Closure $next)
{
    Tenancy::init($request->tenant);

    return $next($request);
}

我覆盖了Tenant model上的getRouteKeyName方法,以使用id以外的数据库列:

public function getRouteKeyName()
{
    return 'domain';
}

最后,我编写了下面的特性测试用例对其进行测试:

\Illuminate\Support\Facades\Route::tenancy(function () {
    \Illuminate\Support\Facades\Route::get('/test', fn () => 'hello world');
});

$tenant = Tenant::factory()->create([
    'domain' => 'demo',
    'name' => 'demo name',
]);

$this->get('http://demo.example.com/test')->assertStatus(200);

$this->assertEquals(Tenancy::tenant()->id, $tenant->id);
$this->assertEquals(Tenancy::domain(), $tenant->domain);
$this->assertEquals(Tenancy::name(), $tenant->name);

但我会得到错误:

testing.ERROR: App\TenancyMananger::init(): Argument #1 ($tenant) must be of type App\Models\Tenant, string given

看起来route没有触发模型绑定,因此$request->tenant int the middleware将字符串(子域)传递到TenancyMananger中。
你知道这里会发生什么吗?否则我不能这样写测试...
如有任何帮助或指导,不胜感激。
我使用的是PHP 8.1、Laravel 10.x-dev和phpunit v9.5.27。
谢谢。

iklwldmw

iklwldmw1#

当你使用这个Tenancy::init($request->tenant); Laravel将Model绑定到路径上。

$tenant = $request->route('tenant');
Tenancy::init($tenant);

return $next($request);

并确保已将Tenancy类添加到$routeMiddleware

相关问题