PHPUnit file upload form

Submitted by MehdiSouihed - 8 years ago

Often you have a form in your application that has a file input (logo, picture, etc...) and you would like to test it. You might have been stuck when trying to test that form, puzzled at the odd errors you got while you did used the attach() method provided in the Laravel Integrated test package. I will show you how to smoothly send a file to your server when you run your PHPUnit test suite.

// Put this function in a helpers.php or a class (can be called statically) or anywhere you like
function prepareFileUpload($path)
{
    TestCase::assertFileExists($path);

    $finfo = finfo_open(FILEINFO_MIME_TYPE);

    $mime = finfo_file($finfo, $path);

    return new \Symfony\Component\HttpFoundation\File\UploadedFile ($path, null, $mime, null, null, true);
}
        
        //In your test file :
        
    // Fill up your form array
    $form = $this->someFakeData()
        
    $form['file'] = prepareFileUpload('public/upload/file.pdf');
         
    $this->visit($myUrl)->submitForm('Submit', $form);
        
        //... Continue your checks .. see(), assert(), etc..
        
    //--------------
    // If you have a mime rule in your validator, the above will not work 
    // (see below to make it work) :
    // This will reject your form
     'file' => 'required|mimes:pdf',
     
     /*
     You will get an error in these terms : file must be of one these types: pdf
     
    This is because the above rule checks against the mimeType sent by the browser 
    (which is not a terribly good practice) and the PHPUnit crawler always sends
    a mime type of 'application/octet-stream' and then laravel winges.
    So to make the server check itself the mimeType and not rely on the browser,
    we have to define a custom validator rule:
     */
     
     // AppServiceProvider class
     
     class AppServiceProvider extends ServiceProvider {

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
          Validator::extend('is_pdf', function($attribute, $value, $parameters, $validator) {

            $mime = \Request::file($attribute)->getMimeType();
            return $mime == 'application/pdf';
        });
    }
     // And use it in your validator:
     
     'file' => 'required|is_pdf',
  //...