Laravel 在测试模式下重置路由参数

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

假设我的应用程序中有以下中间件,它从路由 URL 获取用户的区域设置,然后让它忘记避免将未使用的参数传递给每个控制器操作:

<?php

namespace App\Http\Middleware;

use App\Enums\LocaleEnum;
use App\Models\Patient;
use App\Models\Vendee;
use App\Services\LocaleService;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class LocaleChangerMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        $routeLocale = $request->route('locale');
        $request->route()->forgetParameter('locale');
        $routeLocale = LocaleEnum::tryFrom($routeLocale);

        if (!$routeLocale) {
            throw new NotFoundHttpException;
        }

        $request->mergeIfMissing(['locale' => $routeLocale->value]);

        # set laravel locale
        app()->setLocale($routeLocale->value);

        # check if logged in
        $user = operator();
        if (!$user) {
            return $next($request);
        }

        # check if user supports locale
        $userHasLocale = $user instanceof Patient || $user instanceof Vendee;
        if (!$userHasLocale) {
            return $next($request);
        }

        # check if user has already the same locale
        if ($user->locale === $routeLocale) {
            return $next($request);
        }

        LocaleService::make()->setLocale($user, $routeLocale);

        return $next($request);
    }
}

到目前为止一切工作正常,现在我想在不同的测试用例中添加我的操作(API),如下所示:

<?php

namespace Tests\Feature\Patient;

use Illuminate\Testing\TestResponse;

class AuthTest extends PatientBaseTest
{
    public function test_request_otp_sent_correctly()
    {
        $response = $this->requestOtp('09123456789');
        $response->assertStatus(200);
        $response->assertJsonStructure([
            'data' => [
                'message',
                'validity_duration',
                'resend_delay',
                'code',
            ],
        ]);
    }

    public function test_request_otp_detects_too_many_requests()
    {
        $this->requestOtp('09123456789')->dd();
    }

    private function requestOtp(string $mobile): TestResponse
    {
        $url = $this->uri('auth/request-otp', [], true);
        // above line returns: "http://localhost/fa/v1/auth/request-otp"

        return $this->post($url, ['mobile' => $mobile]);
    }
}

在第一个测试中

test_request_otp_sent_correctly
,一切工作正常,如果我单独运行每个测试也工作正常,但是当我尝试一起运行所有测试时,它说
404 Not found
,我已经追踪到它并发现这是因为
$request->route()->forgetParameter('locale');
在我的中间件中。

现在的问题是:我可以做一些事情来在不同的类似容器的环境中运行每个测试吗?或者有什么解决方案吗?

老实说,这对我来说真的很奇怪。

我跟踪了这一行:带有断点的

$routeLocale = $request->route('locale');
,它在第一个请求中工作正常,但在那之后,它无缘无故地
null

php laravel testing laravel-testing
1个回答
0
投票

如果我正确理解您的问题,则您将从 URL 中删除

locale
(由于中间件),并且
locale
,在本例中
http://localhost/fa/v1/auth/request-otp
将是
fa

当您遇到这样的问题时,通常意味着您没有正确设置测试,在您的情况下,如果我没有感到困惑的话,原因是:

private function requestOtp(string $mobile): TestResponse
{
    $url = $this->uri('auth/request-otp', [], true);
    // above line returns: "http://localhost/fa/v1/auth/request-otp"

    return $this->post($url, ['mobile' => $mobile]);
}

老实说,我以前从未在测试中使用过

$this->uri()
,所以它是您100%自定义的,您需要共享该代码的功能,但是您正在使用依赖于动态变量的东西,所以当中间件运行时,您有一个没有
locale
的新 URL,而
uri
不知道这一点,因此它也将其删除(不需要)。

请暂时停止使用

$this->uri
,并像这样写(只是为了看看这是否解决了问题):

private function requestOtp(string $mobile): TestResponse
{
    return $this->post("/fa/v1/auth/request-otp/{$url}", ['mobile' => $mobile]);
}
© www.soinside.com 2019 - 2024. All rights reserved.