PHPUnit: ожидаемый код состояния 200, но получено 419 с Laravel
Я хочу протестировать метод delete, но я не получаю ожидаемых результатов от 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');
}





Ответы - PHPUnit: ожидаемый код состояния 200, но получено 419 с Laravel / PHPUnit: Expected status code 200 but received 419 with Laravel

20.09.2017 06:57:19
Иногда при тестировании вам нужно будет отключить промежуточные программы, чтобы продолжить :
use Illuminate\Foundation\Testing\WithoutMiddleware;
class ClassTest extends TestCase
{
use WithoutMiddleware; // use this trait
//tests here
}
и если вы хотите отключить их только для одного конкретного теста используйте :
$this->withoutMiddleware();


16.01.2018 03:41:27
Решение: при кэшировании файлов конфигурации вы можете решить эту проблему, запустив php artisan config:clear
.
Объяснение: причина, по которой это может решить проблему, заключается в том, что PHPUnit будет использовать кэшированные значения конфигурации вместо переменных, определенных в тестовой среде. В результате APP_ENV
не настроен на тестирование, и VerifyCsrfTokenMiddleware
выдаст исключение TokenMismatchException
(код состояния 419).
Он не будет выдавать это исключение, когда APP_ENV
настроен на тестирование, так как метод дескриптора
VerifyCsrfTokenMiddleware
проверяет, выполняются ли модульные тесты с VerifyCsrfTokenMiddleware
.
Рекомендуется не кэшировать конфигурацию в среде разработки. Если вам нужно кэшировать конфигурацию в среде, где также выполняются модульные тесты, вы можете очистить кэш вручную в своем $this->runningUnitTests()
:
TestCase.php
Пример на основе https://github.com/laravel/framework/issues/13374#issuecomment-239600163



26.05.2018 07:37:52
измените файл app/Http/Middleware/VerifyCsrfToken.php
путем добавления:
public function handle($request, \Closure $next)
{
if ('testing' !== app()->environment())
{
return parent::handle($request, $next);
}
return $next($request);
}

27.05.2019 10:13:58
Сообщение здесь действительно связано с промежуточным программным обеспечением CSRF. Но есть гораздо лучший способ борьбы с этой проблемой, чем отключение промежуточного программного обеспечения.
Промежуточное ПО поставляется со встроенным кодом, который определяет, используется ли оно в тесте. Этот чек ищет 2 вещи:
- Я управляюсь через командную строку
- Выполняется ли я в среде типа
testing
По умолчанию, правильная настройка программного обеспечения правильно приводит к тому, что оба флага будут истинными при запуске PHP unit. Однако наиболее вероятным виновником является значение в вашем APP_ENV
. Общие способы для этого, чтобы быть неправильным включают в себя:
- Неправильно
phpunit.xml
-файл. Он должен содержать<server name="APP_ENV" value="testing" />
- Сеанс оболочки, имеющий явное значение, установленное в
APP_ENV
которое переопределяет это значение - Сеанс Docker / docker-compose/kubernetes, имеющий явное значение, установленное в
APP_ENV
. Видя о получении этого значения, установленного через .env и / или phpunit.xml-файлы, возможно, лучше, если это возможно. Или обеспечение процесса сборки/тестирования, задающего значение.
Это тоже поставило меня в тупик, и я не был уверен, что мне понадобится использование WithoutMiddleware
, поскольку я не делал этого для другого проекта, но оказалось, что я экспериментировал с чем-то в командной строке и переиграл APP_ENV
в bash.

16.12.2019 11:23:30
Это точное решение.:
Среда 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 ('APP_ENV'), который установлен.ОКР.файл тестирования с
APP_ENV=testing