我想测试删除方法,但我没有从PHPUnit获得预期的结果。我在运行测试时收到此消息:
Expected status code 200 but received 419. Failed asserting that false is true.
/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:77
/tests/Unit/CategoriesControllerTest.php:70
Laravel版本:5.5
感谢您的帮助!
控制器构造函数:
public function __construct()
{
$this->middleware('auth');
$this->middleware('categoryAccess')->except([
'index',
'create'
]);
}
控制器方法:
public function destroy($categoryId)
{
Category::destroy($categoryId);
session()->flash('alert-success', 'Category was successfully deleted.');
return redirect()->action('CategoriesController@index');
}
categoryAccess中间件:
public function handle($request, Closure $next)
{
$category = Category::find($request->id);
if (!($category->user_id == Auth::id())) {
abort(404);
}
return $next($request);
}
类别模型:
protected $dispatchesEvents = [
'deleted' => CategoryDeleted::class,
];
事件监听器
public function handle(ExpensesUpdated $event)
{
$category_id = $event->expense->category_id;
if (Category::find($category_id)) {
$costs = Category::find($category_id)->expense->sum('cost');
$category = Category::find($category_id);
$category->total = $costs;
$category->save();
}
}
PHPUnit删除测试:
use RefreshDatabase;
protected $user;
public function setUp()
{
parent::setUp();
$this->user = factory(User::class)->create();
$this->actingAs($this->user);
}
/** @test */
public function user_can_destroy()
{
$category = factory(Category::class)->create([
'user_id' => $this->user->id
]);
$response = $this->delete('/category/' . $category->id);
$response->assertStatus(200);
$response->assertViewIs('category.index');
}
答案 0 :(得分:8)
有时在测试中,您需要禁用中间件才能继续:
use Illuminate\Foundation\Testing\WithoutMiddleware;
class ClassTest extends TestCase
{
use WithoutMiddleware; // use this trait
//tests here
}
如果你想仅为一个特定的测试用途禁用它们:
$this->withoutMiddleware();
答案 1 :(得分:7)
缓存配置文件后,您可以通过运行php artisan config:clear
来解决此问题。
答案 2 :(得分:0)
通过添加:
修改文件app/Http/Middleware/VerifyCsrfToken.php
public function handle($request, \Closure $next)
{
if ('testing' !== app()->environment())
{
return parent::handle($request, $next);
}
return $next($request);
}
答案 3 :(得分:0)
这里的消息确实与CSRF中间件有关。但是,比禁用中间件还有更好的方法来解决此问题。
中间件带有内置代码,用于检测测试中是否正在使用该中间件。此检查查找2件东西:
testing
环境类型下运行默认情况下,正确安装软件会在运行PHP单元时正确地导致两个标志都为true。但是,最可能的罪魁祸首是您的APP_ENV
中的值。导致此错误的常见方法包括:
phpunit.xml
文件配置错误。它应包含<server name="APP_ENV" value="testing" />
APP_ENV
中设置了显式值的shell会话,该会话会覆盖此值APP_ENV
中设置了显式值的Docker / docker-compose / kubernetes会话。如果可能的话,通过.env和/或phpunit.xml文件查看获取此值集可能会更好。或确保构建/测试过程设置了值。这个人也让我感到难过,我不相信我需要使用WithoutMiddleware
,因为我没有使用其他项目,但是事实证明,我已经在命令行上进行了一些试验并覆盖了APP_ENV
扑面而来。
答案 4 :(得分:0)
这是确切的解决方案:
Laravel环境将在引导应用程序后设置,因此您不能从appServiceProvider或其他源进行更改。 要修复此错误,您需要将此函数添加到App \ Http \ Middleware \ VerifyCsrfToken
public function handle($request, \Closure $next)
{
if(env('APP_ENV') !== 'testing')
{
return parent::handle($request, $next);
}
return $next($request);
}
您需要使用
在.env.testing文件中设置的env('APP_ENV')APP_ENV=testing