假设我的应用程序中有以下中间件,它从路由 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
。
如果我正确理解您的问题,则您将从 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]);
}