Testing File Uploads with Laravel

27,760

In this tutorial, we will see how we can test file uploads with laravel. We will create a very simple form to upload the file. Furthermore, we will test file uploads using laravel.

Create a new View

Let’s start by creating a simple view. Create a new file named upload.blade.php in the resources/views directory. Copy the contents below to the upload view.

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>

    <form action="/upload" method="post" enctype="multipart/form-data">
        {{ csrf_field() }}
        <input type="file" accept="image/*" name="file">

        <button type="submit">Submit</button>
    </form>

</body>
</html>

Routes

Add the following two routes in your routes/web.php file.

Route::get('/upload', 'UploadController@index');
Route::post('/upload', 'UploadController@store');

One route will be used to show the form and the other route will be used to handle upload.

Application Logic

Run the following command to create a new Upload Controller.

php artisan make:controller UploadController

Migration file

Let’s create a new migration and a model for the Upload file. Run the following command to create a new model Upload and a migration as well.

php artisan make:model Upload -m

Go to the create_uploads_table.php file in the database/migrations directory and replace the up method contents with the contents written below.

Schema::create('uploads', function (Blueprint $table) {
    $table->increments('id');
    $table->string('file');
    $table->timestamps();
});

We will be saving the path of the uploaded file in the file column.

Upload Model

Go to the Upload model and add the following to avoid mass assignment exception.

protected $guarded = [];

In a real application, you would rather use $fillable property.

Upload Controller

Now, copy the contents below to the UploadController.php file.

<?php

namespace App\Http\Controllers;

use App\Upload;
use Illuminate\Http\Request;

class UploadController extends Controller
{
    public function index()
    {
        return view('upload');
    }

    public function store(Request $request)
    {
        Upload::create([
            'file' => $request->file('file')->store('file', 'public')
        ]);

        if ($request->wantsJson()) {
            return response([], 204);
        }

        return back();
    }
}

In the index method, we are simply returning the view. In the store method, we are storing the name of the file. $request->file('file')->store('file', 'public') returns the hashed file name and at the same time store the file on the disk.

Our back-end logic is set up.

Testing File Upload

Let’s get down to the real thing: Testing File uploads. Run the following command to create a new Feature test.

php artisan make:test UploadTest

Open UploadTest.php file in the tests/Feature directory. Replace the contents of the file with the contents below.

<?php

namespace Tests\Feature;

use App\Upload;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class UploadTest extends TestCase
{
    /** @test */
    function upload_file_test()
    {
        Storage::fake('public');

        $this->json('post', '/upload', [
            'file' => $file = UploadedFile::fake()->image('random.jpg')
        ]);

        $this->assertEquals('file/' . $file->hashName(), Upload::latest()->first()->file);

        Storage::disk('public')->assertExists('file/' . $file->hashName());
    }
}

In the upload_file_test first we are simply calling Storage::fake('public');. It will replace the given disk with a local testing disk named public.

In the next line, we are pushing a post request to the /upload route which will hit the store method in the Upload Controller. We are creating a new fake image with the name random.jpg by using UploadedFile::fake()->image('random.jpg'). Laravel actually creates a new black image and save it in the PHP temp directory. You can pass width and height to the image method if you want. Default is 10 by 10. If have a minimum width and height validation setup, you can pass the parameters.

Next, we are checking if the name of the file exists in the database. It is simply finding the latest entry in the database and checking its file property to be equal to the hash name of the file.

Finally on the public disk, which we created in the first step by calling fake method, we are checking if the file exists.

That’s all what you need to test file Uploads file with Laravel. Hopefully it will help you in your projects.

You might also like
Comments