如何在 Laravel 测试中禁用选定的中间件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34357350/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Disable Selected Middleware in Laravel Tests
提问by surfer190
So it is common that errors from Authentication and CSRF arise when running phpunit
.
因此,在运行phpunit
.
So in the TestCase we use:
所以在测试用例中我们使用:
use WithoutMiddleware;
use WithoutMiddleware;
The problem with this is that when forms fail, it usually comes back with a Flash Message and Old Input. We have disabled all middleware so we have no access to Input::old('username');
or the flash message.
问题在于,当表单失败时,它通常会返回一个 Flash 消息和旧输入。我们已禁用所有中间件,因此我们无法访问Input::old('username');
或闪存消息。
Furthermore our tests of this failed form post returns:
此外,我们对这个失败的表单发布的测试返回:
Caused by
exception 'RuntimeException' with message 'Session store not set on request.
Is there a way to enable the Session Middleware and disable everything else.
有没有办法启用会话中间件并禁用其他所有内容。
回答by Enijar
The best way I have found to do this isn't by using the WithoutMiddleware
trait but by modifying the middleware you want to disable. For example, if you want to disable the VerifyCsrfToken
middleware functionality in your tests you can do the following.
我发现做到这一点的最佳方法不是使用WithoutMiddleware
trait,而是通过修改要禁用的中间件。例如,如果您想VerifyCsrfToken
在测试中禁用中间件功能,您可以执行以下操作。
Inside app/Http/Middleware/VerifyCsrfToken.php
, add a handle
method that checks the APP_ENV
for testing.
在里面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);
}
This will override the handle
method inside of Illuminate\Foundation\Http\Middleware\VerifyCsrfToken
, disabling the functionality entirely.
这将覆盖handle
内部的方法Illuminate\Foundation\Http\Middleware\VerifyCsrfToken
,完全禁用该功能。
回答by patricus
Laravel >= 5.5
Laravel >= 5.5
As of Laravel 5.5, the withoutMiddleware()
method allows you to specify the middleware to disable, instead of disabling them all. So, instead of modifying all of your middleware to add env checks, you can just do this in your test:
从 Laravel 5.5 开始,该withoutMiddleware()
方法允许您指定要禁用的中间件,而不是将它们全部禁用。因此,无需修改所有中间件以添加 env 检查,您只需在测试中执行以下操作:
$this->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class);
Laravel < 5.5
Laravel < 5.5
If you're on Laravel < 5.5, you can implement the same functionality by adding the updated method to your base TestCase class to override the functionality from the framework TestCase.
如果您使用的是 Laravel < 5.5,您可以通过将更新的方法添加到基本 TestCase 类来覆盖框架 TestCase 中的功能来实现相同的功能。
PHP >= 7
PHP >= 7
If you're on PHP7+, add the following to your TestCase class, and you'll be able to use the same method call mentioned above. This functionality uses an anonymous class, which was introduced in PHP7.
如果您使用的是 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
If you're on PHP < 7, you'll have to create an actual class file, and inject that into the container instead of the anonymous class.
如果您使用的是 PHP < 7,则必须创建一个实际的类文件,并将其注入容器而不是匿名类。
Create this class somewhere:
在某处创建这个类:
class FakeMiddleware
{
public function handle($request, $next)
{
return $next($request);
}
}
Override the withoutMiddleware()
method in your TestCase
and use your FakeMiddleware
class:
覆盖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;
}
回答by Atila Silva
You can use trait in test:
您可以在测试中使用特征:
use Illuminate\Foundation\Testing\WithoutMiddleware;
使用 Illuminate\Foundation\Testing\WithoutMiddleware;
Laravel >= 5.7
Laravel >= 5.7