Тестовый Laravel Controller try catch

Я использую Laravel 5.7 и у меня есть этот контроллер

public function upload(Request $request)
{
    $fileData   = $request->getContent();
    $fileName   = uniqid().'.xlsx';

    try {
        // save file locally
        Storage::disk('local')->put($fileName, $fileData);

        // dispatch to queue
        AnyJob::dispatch($fileName);

        // insert in import_statuses table for status checking
        AnyModel::create([
            'job_id'  => $fileName
        ]);

    } catch (\Exception $e) {
        error_log($e);

        return response()->json([
            'error' => 'Could not save file or queue not found.'
        ], 500);
    }

    return response()->json([
        'status' => 'OK',
        'jobId'  => $fileName,
    ]);
}

И я пытаюсь создать тест, который входит в улов, но я не могу заставить его работать.

Я уже пытался издеваться над Storage и ожидать вызова методов disk и put, но он всегда жалуется на то, что другие методы вызываются, а не ожидаются.

Я также пытался издеваться над AnyJob и AnyModel разными способами, но это, похоже, не влияет на запрос, сделанный $this->post.

Это мой метод тестирования прямо сейчас:

public function testUploadException()
{
    $xlsxFile = UploadedFile::fake()->create('test.xlsx', 100);

    // ignore Storage and Job real work
    \Illuminate\Support\Facades\Storage::fake();
    $this->withoutJobs();

    $mock = Mockery::mock('\App\AnyModel');
    $mock
        ->shouldReceive('create')->times(3)
        ->andThrow(new \Exception('any error'));

    $this->app->instance('\App\AnyModel', $mock);

    $response = $this
        ->withHeaders(['content-type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'])
        ->post('/api/upload', [$xlsxFile]);

    $response
        ->assertStatus(500)
        ->assertJson([
            'error' => 'Could not save file or queue not found.'
        ]);
}

И что он возвращает

root@3e5d84a4db42:/application/api# vendor/bin/phpunit 
PHPUnit 7.5.4 by Sebastian Bergmann and contributors.

....F                                                               5 / 5 (100%)

Time: 2.62 seconds, Memory: 20.00MB

There was 1 failure:

1) Tests\Feature\UploadTest::testUploadException
Expected status code 500 but received 200.
Failed asserting that false is true.

/application/api/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:133
/application/api/tests/Feature/UploadTest.php:50

FAILURES!
Tests: 5, Assertions: 8, Failures: 1.

Какую версию Laravel вы используете?

Rwd 15.03.2019 09:45

@РоссУилсон 5.7

Edson Horacio Junior 15.03.2019 17:02
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
0
2
1 158
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Основная причина, по которой это не сработает, заключается в том, что вы не разрешаете модель из IoC, например. используя app() или внедрение зависимостей. Это будет работать с фасадами, но не с моделями Eloquent.

Вы можете изменить определение метода контроллера на следующее, чтобы разрешить класс из контейнера:

public function upload(Request $request, AnyModel $anyModel)

Тогда ваш вызов create будет:

$anyModel->create([
    'job_id'  => $fileName
]);

В вашем тесте также есть несколько проблем:

  1. Полное имя класса — 'App\AnyModel', а не '\App\AnyModel'. Я бы предложил использовать ::сорт вместо использования строки, т.е. AnyModel::class (убедитесь, что вы импортировали класс).
  2. Кажется, вы звоните create() только один раз, поэтому наличие ->times(3) вызовет ошибку.

Я случайно оставил times(3), когда пытался получить ошибки модульного тестирования. Спасибо за ответ

Edson Horacio Junior 21.03.2019 03:37

Помимо использования IoC, о котором говорил @RossWilson, я также обнаружил, что могу попасть в блок catch, используя

Storage::shouldReceive('disk')->andThrow('error');

Другие вопросы по теме