web-dev-qa-db-fra.com

Comment tester le téléchargement de fichiers avec laravel et phpunit?

J'essaie d'exécuter ce test fonctionnel sur mon contrôleur laravel. J'aimerais tester le traitement des images, mais je veux aussi simuler le téléchargement d'images. Comment puis-je faire cela? J'ai trouvé quelques exemples en ligne mais aucun ne semble fonctionner pour moi. Voici ce que j'ai

public function testResizeMethod()
{
    $this->prepareCleanDB();

    $this->_createAccessableCompany();

    $local_file = __DIR__ . '/test-files/large-avatar.jpg';

    $uploadedFile = new Symfony\Component\HttpFoundation\File\UploadedFile(
        $local_file,
        'large-avatar.jpg',
        'image/jpeg',
        null,
        null,
        true
    );


    $values =  array(
        'company_id' => $this->company->id
    );

    $response = $this->action(
        'POST',
        'FileStorageController@store',
        $values,
        ['file' => $uploadedFile]
    );

    $readable_response = $this->getReadableResponseObject($response);
}

Mais le contrôleur n'a pas réussi ce contrôle:

elseif (!Input::hasFile('file'))
{
    return Response::error('No file uploaded');
}

Donc le fichier n'est pas passé correctement. Comment puis-je m'y prendre?


Mettre à jour

Basé sur la suggestion de max.lanin, j'ai aussi essayé:

public function setUp()
{
    // Tried with parent::setUp() here and at the end
    // parent::setUp();
    $local_file = __DIR__ . '/test-files/large-avatar.jpg';

    print($local_file);

    $_FILES = array(
        'file' => array (
            'tmp_name' => $local_file,
            'name' => 'large-avatar.jpg',
            'type' => 'image/jpeg',
            'size' => 335057,
            'error' => 0,
        ),
        'image' => array (
            'tmp_name' => $local_file,
            'name' => 'large-avatar.jpg',
            'type' => 'image/jpeg',
            'size' => 335057,
            'error' => 0,
        ),
    );

    parent::setUp();
}

mais sans succès. Le fichier utilisé existe et sa taille est correcte.

16
Jasper Kennis

Docs for CrawlerTrait.html # method_action reads:

Paramètres
chaîne $ méthode
string $ action
tableau $ wildcards
tableau $ paramètres
tableau $ cookies
tableau $ fichiers
tableau $ serveur
string $ content 

Donc, je suppose que le bon appel devrait être

$response = $this->action(
    'POST',
    'FileStorageController@store',
    [],
    $values,
    [],
    ['file' => $uploadedFile]
);

à moins que des caractères génériques et des cookies ne soient pas vides.

En remarque, il ne s’agit nullement d’un test unité.

10
Alex Blex

Pour tous ceux qui tombent sur cette question, vous pouvez désormais le faire:

    $response = $this->postJson('/product-import', [
        'file' => new \Illuminate\Http\UploadedFile(resource_path('test-files/large-avatar.jpg'), 'large-avatar.jpg', null, null, null, true),
    ]);
6
Mikael

Avec phpunit, vous pouvez attacher un fichier à un formulaire en utilisant la méthode attach ().

Exemple tiré de Lumen docs :

public function testPhotoCanBeUploaded()
{
    $this->visit('/upload')
         ->name('File Name', 'name')
         ->attach($absolutePathToFile, 'photo')
         ->press('Upload')
         ->see('Upload Successful!');
}
5
Alex Kyriakidis

Voici un exemple complet sur la façon de tester des fichiers personnalisés. J'avais besoin de ça pour analyser les fichiers CSV avec un format connu, donc mes fichiers devaient avoir un formatage et un contenu exacts. Si vous avez juste besoin d'images ou de fichiers de taille aléatoire, utilisez les méthodes $ file-> fake-> image () ou create (). Ceux-ci sont livrés avec Laravel.

namespace Tests\Feature;

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

class PanelistImportTest extends TestCase
{
    /** @test */
    public function user_should_be_able_to_upload_csv_file()
    {
        // If your route requires authenticated user
        $user = Factory('App\User')->create();
        $this->actingAs($user);

        // Fake any disk here
        Storage::fake('local');

        $filePath='/tmp/randomstring.csv';

        // Create file
        file_put_contents($filePath, "HeaderA,HeaderB,HeaderC\n");

        $this->postJson('/upload', [
            'file' => new UploadedFile($filePath,'test.csv', null, null, null, true),
        ])->assertStatus(200);

        Storage::disk('local')->assertExists('test.csv');
    }
}

Voici le contrôleur pour aller avec elle:

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage;

class UploadController extends Controller
{
    public function save(Request $request)
    {
        $file = $request->file('file');

        Storage::disk('local')->putFileAs('', $file, $file->getClientOriginalName());

        return response([
            'message' => 'uploaded'
        ], 200);
    }
}
2
Juha Vehnia

Ajoutez la méthode setUp() similaire dans votre test case:

protected function setUp()
{
    parent::setUp();

    $_FILES = array(
        'image'    =>  array(
            'name'      =>  'test.jpg',
            'tmp_name'  =>  __DIR__ . '/_files/phpunit-test.jpg',
            'type'      =>  'image/jpeg',
            'size'      =>  499,
            'error'     =>  0
        )
    );
}

Cela va fausser votre $ _FILES global et laisser Laravel penser qu'il y a quelque chose de téléchargé.

1
Maxim Lanin

Importez d'abord les choses nécessaires

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

Créez ensuite un faux fichier à télécharger.

Storage::fake('local');
$file = UploadedFile::fake()->create('file.pdf');

Créez ensuite une donnée JSON pour transmettre le fichier. Exemple

$parameters =[
            'institute'=>'Allen Peter Institute',
            'total_marks'=>'100',
            'aggregate_marks'=>'78',
            'percentage'=>'78',
            'year'=>'2002',
            'qualification_document'=>$file,
        ];

Envoyez ensuite les données à votre API.

$user = User::where('email','[email protected]')->first();

$response = $this->json('post', 'api/user', $parameters, $this->headers($user));

$response->assertStatus(200);

J'espère que ça va marcher.

1
Inamur Rahman