测试 Laravel Controller 的 try catch
Posted
技术标签:
【中文标题】测试 Laravel Controller 的 try catch【英文标题】:Test Laravel Controller's try catch 【发布时间】:2019-08-06 01:52:32 【问题描述】:我正在使用 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,
]);
我正在尝试创建一个进入 catch 的测试,但我无法让它工作。
我已经尝试模拟 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? @RossWilson 5.7 【参考方案1】:这不起作用的主要原因是您没有从 IoC 解析模型,例如使用app()
或依赖注入。这将适用于外观,但不适用于 Eloquent 模型。
您可以将控制器方法定义更改为以下内容以从容器中解析类:
public function upload(Request $request, AnyModel $anyModel)
那么您对create
的调用将是:
$anyModel->create([
'job_id' => $fileName
]);
您的测试中也存在一些问题:
-
类的完全限定名称是
'App\AnyModel'
而不是'\App\AnyModel'
。我建议使用::class 而不是使用字符串,即AnyModel::class
(确保您已导入该类)。
您似乎只调用了一次create()
,因此使用->times(3)
会引发错误。
【讨论】:
当我试图从单元测试中获取错误时,我不小心离开了times(3)
。谢谢你的回答【参考方案2】:
除了@RossWilson 谈到的使用 IoC 之外,我还发现我可以通过使用陷入 catch 块中
Storage::shouldReceive('disk')->andThrow('error');
【讨论】:
以上是关于测试 Laravel Controller 的 try catch的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 中 Controller访问Model函数/常量
Laravel - Route::resource 与 Route::controller