Как выполнить модульное тестирование с помощью Laravel Localization?
Я использую mcamara/laravel-localization
пакет, и я не могу понять, как заставить его работать с моими модульными тестами. Оба из следующего терпят неудачу с красным:
// 1. This one results in "Redirecting to http://myapp.dev/en"
$this->get('/')->assertSee('My App Homepage');
// 2. This one results in 404
$this->get('/en')->assertSee('My App Homepage');
В браузере http://myapp.dev
возвращает 302 с перенаправлением на http://myapp.dev/en
, справедливо. Тем не мение, http://myapp.dev/en
возвращает 200. Таким образом, оба случая работают на 100% нормально во внешнем интерфейсе, но не с модульными тестами.
Однако у меня есть некоторые настройки, которые, опять же, работают как браузер.
// in web.php
Route::group([
'prefix' => app('PREFIX'), // instead of LaravelLocalization::setLocale()
'middleware' => ['localeSessionRedirect', 'localizationRedirect']],
function() {
Route::get('/', function() {
return view('home');
});
}
]);
// in AppServiceProvider.php
public function boot()
{
// This, unlike LaravelLocalization::setLocale(), will determine the
// language based on URL, rather than cookie, session or other
$prefix = request()->segment(1); // expects 'en' or 'fr'
$this->app->singleton('PREFIX', function($app) use ($prefix) {
return in_array($prefix, ['en', 'fr']) ? $prefix : null;
});
}
Надеюсь, этот код имеет смысл для вас. Спасибо!
ОБНОВИТЬ
Я решил эту проблему с пакетом в выпуске GitHub # 435.
ОБНОВЛЕНИЕ 2
Насколько я мог понять, кажется, что вы можете безопасно тестировать свои локализованные маршруты, если вы указали локаль в базовом URL-адресе в своем файле phpunit XML:
<env name="APP_URL" value="http://myapp.dev/en"/>
Однако это будет работать для ваших локализованных конечных точек GET (которые начинаются с префикса локали, например, 'en'), но не для нелокализованных POST, PUT и т. Д. (Которые не имеют префикса). Следовательно, вы не можете на самом деле тестировать оба вида конечных точек одновременно, если не используете Dusk (чего я не делаю, так как это излишнее и намного медленнее, почти то же самое, что делать это вручную).
2 ответа
Проблема
Используя mcamara/laravel-localization , когда я тестирую маршрут показа, я получаю ошибку 404.
Например, тестирование этого маршрута возвращает мне 404:
Route::get('/posts/{post:slug}', [PostController::class, 'show'])->name('posts.show');
Тест:
/** @test */
public function itShouldDisplayThePostsShowViewToGuestUser()
{
$response = $this->get("/posts/{$this->post1->slug}");
$response->assertStatus(200);
$response->assertViewIs('posts.show');
}
Решение
Я решил скрыть локаль из URL-адреса во время тестирования.
Создание этой переменной env в конце phpunit.xml.
...
<env name="LOCALIZATION_HIDE_DEFAULT_LOCALE" value="true"/>
</php>
</phpunit>
И в config/laravellocalization.php установите hideDefaultLocaleInURL следующим образом:
'hideDefaultLocaleInURL' => env('LOCALIZATION_HIDE_DEFAULT_LOCALE', false)
Это решение было вдохновлено этим сообщением:
https://github.com/mcamara/laravel-localization/issues/161#issuecomment-381367191 .
Я обнаружил, что если вы дамп URL-адреса запроса во время тестирования, это всегда http://myapp.dev
независимо от того, к какой конечной точке вы обращаетесь. Так что оба LaravelLocalization::setLocale()
и мой обычай app('PREFIX')
вернуть null
Это означает, что ни один маршрут никогда не локализуется во время тестирования. Вы облажались в любом случае, потому что, если вы пытаетесь получить доступ к маршруту без префикса локали, вы получаете 302, но если вы укажете локаль, каркас не сможет найти определение для этого маршрута.
Одна статья помогла мне найти временное решение: вам нужно hideDefaultLocaleInURL
в true
в laravellocalization.php
, Таким образом, маршруты, соответствующие вашей локали по умолчанию, не будут иметь префикса, поэтому вы можете проверить их, как если бы они были не локализованы.
Однако проблема все еще сохраняется, потому что как вы должны тестировать свое приложение, когда оно локализовано? (Например, когда у вас есть специфичные для языка маршруты, которые необходимо протестировать). Это ставит вопрос, совместим ли этот пакет даже с модульным тестированием как таковым...