如何在单元测试中将模型绑定到请求

问题描述 投票:0回答:2

我正在努力将模型绑定到单元测试中的请求,以便可以在表单请求中检索模型的关系。

这是表格要求:

class TimeSlotUpdateRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'time' => [
                'required', 'string', 'max:50',
                Rule::unique('time_slots')
                    ->where('schedule_id', $this->timeSlot->schedule->id)
                    ->ignore($this->timeSlot),
            ],
        ];
    }
}

这是测试(

assertExactValidationRules
来自 Jason McCreary 的 Laravel 测试断言包):

/** @test **/
public function it_verifies_the_validation_rules(): void
{
    $timeSlot = TimeSlot::factory()->create();

    $request = TimeSlotUpdateRequest::create(
        route('admin.timeSlots.update', $timeSlot),
        'PATCH'
    )
        ->setContainer($this->app);

    $request->setRouteResolver(function () use ($request) {
        return Route::getRoutes()->match($request);
    });

    $this->assertExactValidationRules([
        'time' => [
            'required', 'string', 'max:50',
            Rule::unique('time_slots')
                ->where('schedule_id', $timeSlot->schedule->id)
                ->ignore($timeSlot->id),
        ],
    ], $request->rules());
}

当从测试和表单请求中删除 where 子句时,测试通过,但由于 where 子句失败并出现错误

ErrorException: Trying to get property 'schedule' of non-object

我尝试使用 xDebug 单步执行请求,但仍然不明白如何路由模型绑定完成。

如何将

$timeSlot
模型绑定请求或路由,以便在表单请求中可以访问
schedule
关系?

任何帮助将不胜感激。

laravel phpunit
2个回答
2
投票

路由模型绑定是通过中间件

SubstituteBindings
中间件处理的。因此请求必须通过中间件堆栈。既然你没有这样做,我想你可以自己设置路线上的参数:

$route->setParameter($name, $value);

$route
是从
match
返回的路线对象。

此外,在处理请求时,如果您想要一个路由参数,您应该明确它并且不要使用动态属性,因为它会在回退到返回路由参数之前返回输入:

$this->route('timeSlot');

0
投票

这是一个老问题,但我也遇到了同样的问题。对于任何对已接受的答案感到困惑的人,以下是建议的更改:

在表单请求中:

...
Rule::unique('time_slots')
    ->where('schedule_id', $this->route('timeSlot')->schedule->id)
    ->ignore($this->route('timeSlot')),
...

在测试中:

...
$request->setRouteResolver(function () use ($request, $timeSlot) {
    $route = Route::getRoutes()->match($request);
    $route->setParameter('timeSlot', $timeSlot);

    return $route;
});
...
© www.soinside.com 2019 - 2024. All rights reserved.