【问题标题】:Calling named routes in laravel tests在 laravel 测试中调用命名路由
【发布时间】:2016-04-07 12:36:48
【问题描述】:

考虑以下几点:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class HomeRouteTest extends TestCase
{
    public function testVisitTheHomePage()
    {
        $response = $this->call('GET', '/');
        $this->assertEquals(200, $response->status());

    }

    public function testVisitTheAboutPage()
    {
        $response = $this->call('GET', '/about');
        $this->assertEquals(200, $response->status());
    }
}

有没有,不是我看到的文档>.>,做类似的事情:

$response = $this->call('GET', 'home.about');
$this->assertEquals(200, $response->status());

或者....你是这样做的吗?

我得到的错误是:

vagrant@scotchbox:/var/www$ phpunit
PHPUnit 4.8.21 by Sebastian Bergmann and contributors.

FF

Time: 3.41 seconds, Memory: 14.25Mb

There were 2 failures:

1) HomeRouteTest::testVisitTheHomePage
Failed asserting that 404 matches expected 200.

/var/www/tests/HomeRouteTest.php:12

2) HomeRouteTest::testVisitTheAboutPage
Failed asserting that 404 matches expected 200.

/var/www/tests/HomeRouteTest.php:19

FAILURES!
Tests: 2, Assertions: 2, Failures: 2.

【问题讨论】:

    标签: unit-testing testing laravel-5 phpunit laravel-5.2


    【解决方案1】:

    说实话,我看不出有什么理由来测试名称路由。命名路由更容易在应用程序内部使用,您应该测试具体的 url 而不是命名路由以确保使用正确的 url。

    如果你真的需要测试命名路由,我会用简单的数组为它创建辅助函数:

    protected function getNamedRoute($name) 
    {
       $routes = [
            'home.about' => '/about',
       ];
    
       return $routes[$name]; 
    }
    

    然后在你的测试中:

    public function testVisitTheHomePage()
    {
        $response = $this->call('GET', $this->getNamedRoute('home.about'));
        $this->assertEquals(200, $response->status());
    }
    

    第二件事是你可以让这些测试更干净一点,你不需要使用:

    $response = $this->call('GET', '/');
    $this->assertEquals(200, $response->status());
    

    你可以使用:

    $this->visit('/')->seeStatusCode(200);
    

    对我来说,它更清晰,您可以编写更少的代码来实现相同的目标。

    【讨论】:

    • 我真的不明白你的测试实际上是如何测试任何东西的。我的系统中已经定义了路由,您似乎只是在测试路由名称存在的事实......
    • 测试命名路由的原因是,当 URL 因重构而改变时,测试继续工作而不被改变(只要路由的名称没有改变)。
    • @Julian 但是,如果您为第 3 方创建 API 并且其中一位开发人员会更改路由 url 而没有实际通知第 3 方,该怎么办?测试将通过(因为它们将使用命名路由),但您的应用程序将无法用于第 3 方,因为在他们的应用程序中,他们使用的不是明显命名的路由,而是 url。
    • 你误会了。您说“我看不出有任何理由测试命名路线”;我给了你一个。我不是说这是唯一的,也不是说这是你在任何情况下都应该做的。每个应用程序都是不同的,测试命名路由是否有意义取决于您的业务规则。
    【解决方案2】:

    这是一个很晚的回复,但我认为您正在寻找的是:

    $this->route('GET', 'home.about');
    $this->assertResponseOk(); // Checks that response status was 200
    

    对于带参数的路由,你可以这样做:

    $this->route('GET', 'users.show', ['id' => 3]); // (goes to '/users/3')
    

    我需要这个来测试我正在使用的一些可怕的路线,看起来像这样:

    Route::resource(
        '/accounts/{account_id}/users',
        'AccountsController@users',
        [
            'parameters' => ['account_id'],
            'names'      => [
                'create'  => 'users.create',
                'destroy' => 'users.destroy',
                'edit'    => 'users.edit',
                'show '   => 'users.show',
                'store'   => 'users.store',
                'update'  => 'users.update',
            ]
        ]
    );
    

    为了确保我的路线和重定向进入正确的页面,我这样做了:

    /**
     * @test
     */
    public function users_index_route_loads_correct_page()
    {
        $account = Account::first();
    
        $response = $this->route('get', 'users.index', ['account_id' => $account->id]);
        $this->assertResponseOk()
            ->seePageIs('/accounts/' . $account->id . '/users');
    }
    

    为了确保我使用的是正确的视图文件(我们都会犯复制粘贴错误,对吧?),我这样做了:

    /**
     * @test
     */
    public function users_index_route_uses_expected_view()
    {
        $account = Account::first();
    
        $response = $this->route('get', 'users.index', ['account_id' => $account->id]);
    
        $view = $response->original; // returns View instance
        $view_name = $view->getName();
    
        $this->assertEquals($view_name, 'users.index'); 
    }
    

    如果不是因为 PHPStorm 中的 Structure 功能和我偶然发现的 Laravel 4.2 的文档,我想我永远不会想出如何测试这些路由。我希望这可以为其他人节省一点时间。

    【讨论】:

    • 这在 Laravel 5.4 中不再有效 - 调用未定义的方法 route()
    • 在更高版本的 laravel 上调用的方法是 call()。
    • call() 返回 404 它的行为与 route() 不同
    【解决方案3】:

    据我所知,此解决方案适用于任何 Laravel 5 版本。尤其是 Laravel 5.4+,不像这里提到的其他解决方案。

    如果你的命名路由有参数,你可以这样做:

    $response = $this->get(route('users.show', [
        'user' => 3,
    ]));
    
    $response->assertStatus(200);
    

    如果你的命名路由没有参数,那么你可以这样做:

    $response = $this->get(route('users.index'));
    
    $response->assertStatus(200);
    

    漂亮又简单。

    【讨论】:

      猜你喜欢
      • 2019-02-18
      • 2020-12-04
      • 1970-01-01
      • 1970-01-01
      • 2010-12-18
      • 1970-01-01
      • 1970-01-01
      • 2012-12-19
      • 2019-08-06
      相关资源
      最近更新 更多