How to test file upload in Laravel 5.2
Solution 1
When you create an instance of UploadedFile
set the last parameter $test
to true
.
$file = new UploadedFile($path, $name, filesize($path), 'image/png', null, true);
^^^^
Here is a quick example of a working test. It expects that you have a stub test.png
file in tests/stubs
folder.
class UploadTest extends TestCase
{
public function test_upload_works()
{
$stub = __DIR__.'/stubs/test.png';
$name = str_random(8).'.png';
$path = sys_get_temp_dir().'/'.$name;
copy($stub, $path);
$file = new UploadedFile($path, $name, filesize($path), 'image/png', null, true);
$response = $this->call('POST', '/upload', [], [], ['photo' => $file], ['Accept' => 'application/json']);
$this->assertResponseOk();
$content = json_decode($response->getContent());
$this->assertObjectHasAttribute('name', $content);
$uploaded = 'uploads'.DIRECTORY_SEPARATOR.$content->name;
$this->assertFileExists(public_path($uploaded));
@unlink($uploaded);
}
}
➔ phpunit tests/UploadTest.php PHPUnit 4.8.24 by Sebastian Bergmann and contributors. . Time: 2.97 seconds, Memory: 14.00Mb OK (1 test, 3 assertions)
Solution 2
In Laravel 5.4 you can also use \Illuminate\Http\UploadedFile::fake()
. A simple example below:
/**
* @test
*/
public function it_should_allow_to_upload_an_image_attachment()
{
$this->post(
action('AttachmentController@store'),
['file' => UploadedFile::fake()->image('file.png', 600, 600)]
);
/** @var \App\Attachment $attachment */
$this->assertNotNull($attachment = Attachment::query()->first());
$this->assertFileExists($attachment->path());
@unlink($attachment->path());
}
If you want to fake a different file type you can use
UploadedFile::fake()->create($name, $kilobytes = 0)
More information directly on Laravel Documentation.
Solution 3
I think this is the easiest way to do it
$file=UploadedFile::fake()->image('file.png', 600, 600)];
$this->post(route("user.store"),["file" =>$file));
$user= User::first();
//check file exists in the directory
Storage::disk("local")->assertExists($user->file);
and I think the best way to delete uploaded files in the test is by using tearDownAfterClass static method, this will delete all uploaded files
use Illuminate\Filesystem\Filesystem;
public static function tearDownAfterClass():void{
$file=new Filesystem;
$file->cleanDirectory("storage/app/public/images");
}
Ramin Omrani
I am a software developer based in Rome, Italy, with a particular focus on the web. I became passionate about programming at the age of 14 when I was a member of the Robocup students' team of Tehran. Since then, my passion for learning new tools and trends in programming has never stopped.
Updated on August 17, 2020Comments
-
Ramin Omrani almost 4 years
Im trying to test an upload API but it fails every time:
Test Code :
$JSONResponse = $this->call('POST', '/upload', [], [], [ 'photo' => new UploadedFile(base_path('public/uploads/test') . '/34610974.jpg', '34610974.jpg') ]); $this->assertResponseOk(); $this->seeJsonStructure(['name']); $response = json_decode($JSONResponse); $this->assertTrue(file_exists(base_path('public/uploads') . '/' . $response['name']));
file path is /public/uploads/test/34610974.jpg
Here is My Upload code in a controller :
$this->validate($request, [ 'photo' => 'bail|required|image|max:1024' ]); $name = 'adummyname' . '.' . $request->file('photo')->getClientOriginalExtension(); $request->file('photo')->move('/uploads', $name); return response()->json(['name' => $name]);
How should I test file upload in Laravel 5.2? How to use
call
method to upload a file? -
schellingerht about 8 yearsThat should work, but it doesn't.
$request->file('photo')
has indeed the UploadFile object, but$test
in this object has its default valuefalse
. Strange, because the new UploadedFile has the $test = true parameter. -
schellingerht about 8 yearsThe answer above is not enough for > 5.2.14. The right answer could you find here: stackoverflow.com/questions/36857800/…
-
Hanson about 7 yearsIt should be
$file = new UploadedFile($path, $name, 'image/png', filesize($path), null, true);
-
Syl almost 7 yearsBut the create() method does not pass the validation if you only ask a specific MIME type such as mp3...
-
Fanan Dala over 3 yearsFor
Symfony 4.1
the correct implementation is$file = new UploadedFile($path, $name, 'image/png', null, true);