如何使用Laravel测试授权重定向?

时间:2016-08-07 08:59:52

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

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

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

手动测试通过,但是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来测试用户是否为admin:

<?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;声明。

3 个答案:

答案 0 :(得分:6)

您有两种选择:

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

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

答案 1 :(得分:6)

暂且不说:unit tests并不是user experience次测试。对于那,将进行acceptancefunctional测试。其中一个比较受欢迎的工具是codeception。结合phantomjsselenium可以模拟浏览器会话并获得完整的用户体验呈现。

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

验收测试:&#39;从用户的角度来看,验收测试可以涵盖标准但复杂的场景。通过验收测试,您可以确信用户在所有已定义的方案中都不会出错。&#39;

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

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

答案 2 :(得分:4)

我建议您使用身份验证用户实例Auth::login($user);了解详情,请阅读here

此方法适用于Laravel 5.x及更高版本