چگونه آپلود شدن فایل ها رو تست کنیم؟

بیشتر چالش های تست نویسی وقتی اتفاق می‌افتند که میخواهیم چیزی خارج از سیستم را تست کنیم. در اینجا میخوام نحوه تست نویسی برای دریافت فایل ها رو در لاراول بررسی کنم.

مثل همیشه سناریو کلی برای اپلود فایل در نظر میگیریم. ابتدا اینکه باید بدونیم از چه سیستمی برای ذخیره کردن فایل ها میخواهیم استفاده کنیم تا بتونیم توی تست اون رو شبیه سازی کنیم. برای این موضوع میتونید به کانفیگ لاراول ( config/filesystems.php) نگاهی بندازید:

‘default’ => env(‘FILESYSTEM_DEFAULT’, ‘local’)

حالا نوبت اون رسیده که درایور مورد نظر رو Mock کنید تا در تست بطور واقعی به سراغش نریم:

Storage::fake('profile-pictures');

سپس به درایور مورد نظرتون یک فایل نمونه با حجم و اندازه و اسم مورد نظرتون معرفی کنید تا در محیط تست یکی از اون بسازه:

UploadedFile::fake()->image('avatar.jpg', $width, $height)->size(100)

بدیهی است که میتونید در اینجا فرمت و اندازه فایل مورد نظر رو هم مورد تست قرار بدید. البته برای ساختن فایل از هر نوع دیگری همچنین میتونید:

UploadedFile::fake()->create('document.pdf', $sizeInKilobytes);

و در آخر باید انتظار داشته باشید تا این فایل رو در درایور مورد نظرتون دریافت کنید:

Storage::disk('profile-pictures')->assertExists('avatar.jpg');

بنظر میاد حالا بتونید از همه اینها برای تست یک کنترلر که گرفتن فایل از Request رو بر عهده داره استفاده کنید:

class FileUploadTest extends TestCase {     
public function it_expect_file_in_storge_after_send_as_a_json_request() {         
Storage::fake('profile-pictures');          
$response = $this->json('POST',  '/images', [             
    'imagefile' => UploadedFile::fake()->image('avatar.jpg')         
    ]); 
 Storage::disk('profile-pictures')->assertExists('avatar.jpg');
  } }

همینطور میتونید نبودن یک فایل رو در موقع پاک کردن اون از storage تست کنید:

Storage::disk('profile-pictures')->assertMissing('missing.jpg');

برای گرفتن فایل از Request لاراول به شما این امکان رو میده تا اسم فایل فرستاده شده رو داشته باشید:

$request->file('imagefile')->name;

و همینطور محتویات اون رو داشته باشید:

$request->file('imagefile');

اون رو در درایور مورد نظرتون (که طبعا متناسب با تستی که نوشتید خواهد بود) ذخیره کنید:

Storage::disk('profile-pictures')->put($yourImageName, $profileImageContents);

و موقعی که میخواهید آدرس مستقیم فایل مورد نظرتون رو در api برگردونید میتونید از این متد استفاده کنید:

asset('storage/profile-pictures' . $imageName)