Having issues testing Amazon S3 file upload controller using Laravel 5.2? Here’s how.
We will be using:
- Laravel 5.2 Validations
- Mockery
- phpunit
Setting up your controller:
Add your file route to app/Http/routes.php file.
1 |
Route::post('/files', 'FileController@store'); |
Create your FileRequest file with the required validations in app/Http/Requests/FileRequest.php :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?php namespace App\Http\Requests; use App\Http\Requests\Request; class FileRequest extends Request { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'file' => 'required|mimes:jpeg,jpg,gif,png', ]; } } |
Create your FileController file at app/Http/Controllers/FileController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<?php namespace App\Http\Controllers; use Exception; use App\Http\Requests\FileRequest; use Illuminate\Contracts\Filesystem\Factory; use Illuminate\Filesystem\Filesystem; class FileController extends Controller { /** * Storage dependency to be injected * * @var Illuminate\Contracts\Filesystem\Factory */ protected $storage; /** * File dependency to be injected * * @var Illuminate\Filesystem\Filesystem */ protected $file; /** * Constructor * * @param */ public function __construct(Factory $storage, Filesystem $file) { $this->storage = $storage; $this->file = $file; } /** * Post file * * @post("/files") */ public function store(FileRequest $request) { $uploadedFile = $request->file('file'); $ext = $uploadedFile->getClientOriginalExtension(); $fileName = uniqid() . ".$ext"; try { $s3 = $this->storage->disk('s3'); $s3->put($fileName, $this->file->get($uploadedFile->getRealPath())); } catch (Exception $ex) { throw new Exception('Not able to store file, details:' . $ex->getMessage()); } } } |
Creating phpunit test
Add your controller test file at tests/FileControllerTest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
<?php use Illuminate\Foundation\Testing\WithoutMiddleware; use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Foundation\Testing\DatabaseTransactions; class FileControllerTest extends TestCase { /** * Storage dependency to be injected to IoC Container * @var */ protected $storage; /** * File dependency to be injected to IoC Container * @var */ protected $file; /** * File System dependency to be injected to IoC Container * @var */ protected $fileSystem; /** * Initial setup * * @return void */ public function setUp() { parent::setUp(); //Setup mocks $this->storage = $this->mock('Illuminate\Contracts\Filesystem\Factory'); $this->file = $this->mock('Illuminate\Contracts\Filesystem'); $this->fileSystem = $this->mock('Illuminate\Filesystem\Filesystem'); } /** * Mock Container dependencies * * @param string $class Class to mock * * @return void */ public function mock($class) { $mock = Mockery::mock($class); $this->app->instance($class, $mock); return $mock; } /** * Test uploaded succesfully * * @return void */ public function testUpdateSuccess() { //Mock image to don't use filesystem $uploadedFile = Mockery::mock( 'Illuminate\Http\UploadedFile', [ 'getClientOriginalName' => 'image-1.jpg', 'getClientOriginalExtension' => 'jpg', 'getPath' => '/path/to/file', 'isValid' => true, 'guessExtension' => 'jpg', 'getRealPath' => null, ] ); $this->fileSystem->shouldReceive('get')->andReturn(true); //Set storage mocks methods $disk = Mockery::mock('\Illuminate\Contracts\Filesystem\Filesystem', ['put' => null]); $this->storage->shouldReceive('disk')->andReturn($disk); $files = [ 'file' => $uploadedFile ]; $this->call('POST', '/files', [], [], $files); $this->assertResponseStatus(200); } /** * Test upload without files * * @return void */ public function testNoFile() { $this->post('/files', [], []); $this->assertSessionHasErrors(['file']); } } |
Finally run phpunit from your Laravel root path.