【问题标题】:How to do unit testing with Laravel Localization?如何使用 Laravel 本地化进行单元测试?
【发布时间】:2017-09-12 09:45:04
【问题描述】:

我正在使用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 issue #435 中解决了这个问题。

更新 2

据我所知,只要您在 phpunit XML 文件的基本 URL 中指定语言环境,您似乎就可以安全地测试本地化路由:

<env name="APP_URL" value="http://myapp.dev/en"/>

但是,这适用于本地化的 GET 端点(以语言环境前缀开头,例如“en”),但不适用于非本地化的 POST、PUT 等(没有任何前缀)。因此,您不能真正同时测试两种端点,除非您使用 Dusk(我不这样做,因为它是一种过度杀伤且速度慢得多,几乎与手动测试相同)。

【问题讨论】:

    标签: laravel phpunit laravel-5.4 laravel-localization


    【解决方案1】:

    我发现如果您在测试期间转储请求 URL,无论您访问哪个端点,它总是 http://myapp.dev。所以LaravelLocalization::setLocale() 和我的自定义app('PREFIX') 都返回null,这意味着在测试期间没有一条路线被本地化。无论哪种方式,您都搞砸了,因为如果您尝试访问没有区域设置前缀的路由,您会得到 302,但如果您确实指定了区域设置,则框架无法找到该路由的定义。

    One article 帮我找到了一个临时解决方案:您需要在laravellocalization.php 中将hideDefaultLocaleInURL 转至true。这样,与您的默认语言环境匹配的路由将没有任何前缀,因此您可以像未本地化一样测试它们。

    但是,问题仍然存在,因为当应用程序 本地化时,您应该如何测试它? (例如,当您有需要测试的特定于语言的路线时)。这就提出了这个包是否与单元测试本身兼容的问题......

    【讨论】:

    • 我也有同样的问题。如果我将hideDefaultLocaleInURL 设置为true,我的单元测试中会出现更多错误。我的解决方案是将useAcceptLanguageHeader 设置为false 并将hideDefaultLocaleInURL 设置为true
    • @poldixd 如果你想将useAcceptLanguageHeader 设置为true,你只需要像这样$response = $this-&gt;withSession(['locale' =&gt; 'en']) -&gt;get('/'); 设置会话就可以了(你仍然需要hideDefaultLocaleInURL
    【解决方案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 中隐藏语言环境的问题。

    在 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-09
      • 2021-06-16
      • 2017-05-15
      • 2013-09-13
      • 2012-01-08
      • 2018-07-21
      • 2017-08-27
      • 1970-01-01
      相关资源
      最近更新 更多