如何在Laravel测试中禁用选定的中间件

时间:2015-12-18 13:58:55

标签: php laravel

因此,运行phpunit时会出现身份验证和CSRF错误。

所以在TestCase中我们使用:

use WithoutMiddleware;

问题在于,当表单失败时,它通常会返回Flash Message和Old Input。我们已禁用所有中间件,因此我们无法访问Input::old('username');或Flash消息。

此外,我们对此失败表单的测试返回:

Caused by
exception 'RuntimeException' with message 'Session store not set on request.

是否有办法启用会话中间件并禁用其他所有内容。

6 个答案:

答案 0 :(得分:19)

我发现这样做的最好方法不是使用WithoutMiddleware特征,而是修改要禁用的中间件。例如,如果要在测试中禁用VerifyCsrfToken中间件功能,可以执行以下操作。

app/Http/Middleware/VerifyCsrfToken.php内添加handle方法,检查APP_ENV是否有测试。

public function handle($request, Closure $next)
{
    if (env('APP_ENV') === 'testing') {
        return $next($request);
    }

    return parent::handle($request, $next);
}

这将覆盖handle内的Illuminate\Foundation\Http\Middleware\VerifyCsrfToken方法,完全禁用该功能。

答案 1 :(得分:5)

Laravel> = 5.5

从Laravel 5.5开始,withoutMiddleware()方法允许您指定要禁用的中间件,而不是全部禁用它们。因此,您无需修改​​所有中间件来添加环境检查,只需在测试中执行以下操作即可:

$this->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class);

Laravel <5.5

如果您使用的是Laravel <5.5,则可以通过将更新的方法添加到基本TestCase类中以覆盖框架TestCase的功能来实现相同的功能。

PHP> = 7

如果您使用的是PHP7 +,请将以下内容添加到TestCase类中,您将可以使用上述相同的方法调用。此功能使用PHP7中引入的匿名类。

/**
 * Disable middleware for the test.
 *
 * @param  string|array|null  $middleware
 * @return $this
 */
public function withoutMiddleware($middleware = null)
{
    if (is_null($middleware)) {
        $this->app->instance('middleware.disable', true);

        return $this;
    }

    foreach ((array) $middleware as $abstract) {
        $this->app->instance($abstract, new class {
            public function handle($request, $next)
            {
                return $next($request);
            }
        });
    }

    return $this;
}

PHP <7

如果您使用的是PHP <7,则必须创建一个实际的类文件,并将其注入容器中,而不是将其注入匿名类中。

在某处创建此类:

class FakeMiddleware
{
    public function handle($request, $next)
    {
        return $next($request);
    }
}

覆盖withoutMiddleware()中的TestCase方法并使用FakeMiddleware类:

/**
 * Disable middleware for the test.
 *
 * @param  string|array|null  $middleware
 * @return $this
 */
public function withoutMiddleware($middleware = null)
{
    if (is_null($middleware)) {
        $this->app->instance('middleware.disable', true);

        return $this;
    }

    foreach ((array) $middleware as $abstract) {
        $this->app->instance($abstract, new FakeMiddleware());
    }

    return $this;
}

答案 2 :(得分:0)

您可以在测试中使用特征:

  

使用Illuminate \ Foundation \ Testing \ WithoutMiddleware;

Laravel> = 5.7

答案 3 :(得分:0)

以下内容对我有用:

use WithoutMiddleware;

public function setUp(): void
{
    parent::setUp();
    $this->withoutMiddleware();
}

答案 4 :(得分:0)

我可能会迟到,但我已经想通了:

$this->withoutMiddleware([
   'email-verified', //alias does NOT work
   EnsureEmailIsVerified::class //Qualified class name DOES WORK
]);

答案 5 :(得分:0)

The withoutMiddleware method can only remove route middleware and does not apply to global middleware.

来自https://laravel.com/docs/8.x/middleware