【问题标题】:How to test an authorization redirect with Laravel?如何使用 Laravel 测试授权重定向?
【发布时间】:2016-12-13 05:52:11
【问题描述】:

我已经手动测试了我想要的场景:

管理员用户可以访问网站的/codes 部分。 普通用户被重定向 (302) 回/dashboard,并在他们转到/qr 时收到一条消息Sorry you are not allowed there

手动测试通过,但 laravel 测试失败。

我正在使用laravel 5.1

测试管理员用户:

public function testAdminViewCodes()
    {
        //create an admin user
        $user = factory(App\User::class, 'admin')->create();

        $this->actingAs($user)
            ->visit('/codes')
            ->seePageIs('/codes')
            ->see('Codes');
    }

普通用户测试:

    public function testNormalViewCodesFail()
    {
        //create a normal user
        $normal_user = factory(App\User::class)->create();

        //TODO: Fix this failing test FFS

        $this->actingAs($normal_user)
             ->visit('/qr')
             ->seePageIs('/dashboard')
             ->see('Sorry you are not allowed there');
}

测试结果

There was 1 failure:

1) AdminTest::testNormalViewQRCodesFail
Did not land on expected page [http://localhost/dashboard].

Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'http://localhost/dashboard'
+'http://localhost/codes'

我认为工厂可能有问题,似乎总是在创建管理员用户:

$factory->define(App\User::class, function (Faker\Generator $faker) {
    return [
        'email' => $faker->email,
        'password' => bcrypt(str_random(10)),
        'remember_token' => str_random(10),
        'is_admin' => false,
    ];
});

$factory->defineAs(App\User::class, 'admin', function ($faker) use ($factory) {
    $user = $factory->raw(App\User::class);

    return array_merge($user, ['is_admin' => true]);
});

对于这个问题持续了多久,我深表歉意,但还有另一个相关问题。我正在使用middleware 来测试用户是否是管理员:

<?php

namespace RMS\Http\Middleware;

use Closure;

class IsAdminMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (app()->env === 'testing') {
            return $next($request);
        }

        if (! $request->user()->isAdmin()) {
          return redirect()->route('dashboard')
              ->with('message', 'Sorry you are not allowed there');
        }

        return $next($request);
    }
}

Kernel.php:

protected $routeMiddleware = [
        'auth' => \RMS\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'guest' => \RMS\Http\Middleware\RedirectIfAuthenticated::class,
        'isadmin' => \RMS\Http\Middleware\IsAdminMiddleware::class,
    ];

并应用于路由:

Route::group(['middleware' => ['auth', 'isadmin']], function()
{
    Route::resource('user', 'UserController');
});

中间件是否被忽略?我确定不会添加use WithoutMiddleware; 语句。

【问题讨论】:

    标签: php laravel unit-testing laravel-5 laravel-5.1


    【解决方案1】:

    你有两个选择:

    • 更好地为用户工厂创建测试,比如它可以创建你想要的用户类型
    • 在用户生成后中断调试器以手动检查它

    我建议您创建测试,因为您现在有疑问,并且将来有可能意外破坏工厂代码,因为它不是那么明显。

    【讨论】:

    • break with a debugger after user generation to inspect it manually 你是怎么做到的。使用 python 有一个很酷的工具,叫做 pdb()ipdb() 是否有与 laravel 等效的工具?
    • PHP 调试器称为XDebug。某些 IDE 中集成了支持,例如 - PHPStorm
    • 是的,但这不会让您在解释过程中进行检查......或者是吗?
    • 确实如此,它还允许您在运行时更改变量并评估自定义代码。当您习惯它时,您可以比使用 var_dump 或类似方法更快地进行调试。
    • 我发现它在与 IDE 集成时可以工作,您的首选 IDE 是什么?
    【解决方案2】:

    顺便说一句:unit tests 并不意味着是 user experience 测试。因为那将是acceptancefunctional 测试。对此比较流行的工具之一是codeception。它与phantomjsselenium 结合可以模拟浏览器会话并获得完整的用户体验呈现。

    http://codeception.com/docs/01-Introduction docs 上提供的每个文档:

    验收测试:'验收测试可以涵盖从用户的角度来看标准但复杂的场景。通过验收测试,您可以确信用户遵循所有定义的场景不会出错。'

    功能测试 : '模拟 Web 请求($_GET 和 $_POST 变量)并将其发送到返回 HTML 响应的应用程序的功能测试。 '

    单元测试:'在将它们耦合在一起之前测试代码片段也非常重要。通过这种方式,您可以确保某些深藏不露的功能仍然有效,即使它没有被功能或验收测试覆盖。这也证明您生成了稳定且可测试的代码。'

    【讨论】:

    • 这不是单元测试,而是借助 Laravel built-it testing tools 进行功能测试。
    • @Pheagey 请在您的答案中写下不同类型测试的定义,然后链接到可靠的资源。维基百科没有删减它。一旦我清楚它是unitfunctionalintegrationend-to-end 测试,我会立即更改问题。这是一个答案,还是一个旁白/评论?
    • 不得不将您作为已接受的答案删除,因为您没有回答问题。我正在测试授权,我没有提到它是一个单元测试。
    【解决方案3】:

    我建议使用 Authenticate a User Instance Auth::login($user); 了解更多详情,请阅读 here

    此方法适用于 Laravel 5.x 及以上版本

    【讨论】:

    猜你喜欢
    • 2020-12-18
    • 1970-01-01
    • 2020-08-09
    • 2016-07-18
    • 2015-06-09
    • 2021-07-22
    • 2015-08-13
    • 2017-06-24
    • 1970-01-01
    相关资源
    最近更新 更多