Я использую 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.
@РоссУилсон 5.7






Основная причина, по которой это не сработает, заключается в том, что вы не разрешаете модель из IoC, например. используя app() или внедрение зависимостей. Это будет работать с фасадами, но не с моделями Eloquent.
Вы можете изменить определение метода контроллера на следующее, чтобы разрешить класс из контейнера:
public function upload(Request $request, AnyModel $anyModel)
Тогда ваш вызов create будет:
$anyModel->create([
'job_id' => $fileName
]);
В вашем тесте также есть несколько проблем:
'App\AnyModel', а не '\App\AnyModel'. Я бы предложил использовать ::сорт вместо использования строки, т.е. AnyModel::class (убедитесь, что вы импортировали класс).create() только один раз, поэтому наличие ->times(3) вызовет ошибку.Я случайно оставил times(3), когда пытался получить ошибки модульного тестирования. Спасибо за ответ
Помимо использования IoC, о котором говорил @RossWilson, я также обнаружил, что могу попасть в блок catch, используя
Storage::shouldReceive('disk')->andThrow('error');
Какую версию Laravel вы используете?