如何在 Laravel 测试中禁用选定的中间件拉拉维尔>= 5.5拉拉维尔 < 5.5

2022-08-30 18:08:49

运行 时,通常会出现来自身份验证和 CSRF 的错误。phpunit

在测试用例中,我们使用:

use WithoutMiddleware;

问题是,当表单失败时,它通常会返回Flash消息和旧输入。我们已经禁用了所有中间件,因此我们无法访问闪存消息。Input::old('username');

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

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

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


答案 1

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

在 里面,添加一个检查测试的方法。app/Http/Middleware/VerifyCsrfToken.phphandleAPP_ENV

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

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

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


答案 2

拉拉维尔>= 5.5

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

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

拉拉维尔 < 5.5

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

>菲律宾比索= 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;
}

< 7 菲律宾比索

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

在以下位置创建此类:

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

重写您的方法并使用您的类:withoutMiddleware()TestCaseFakeMiddleware

/**
 * 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;
}

推荐