2017-05-04 2 views
1

J'ai un peu de problème avec mes tests d'intégration PHPUnit, j'ai une méthode qui gère un téléchargement de formulaire pour un fichier vidéo ainsi qu'une image de prévisualisation pour cette vidéo.Virtual Filesystem pour les tests PHPUnit dans Laravel 5.4

public function store($request) 
{ 
    /** @var Video $resource */ 
    $resource = new $this->model; 

    // Create a new Content before creating the related Photo 
    $contentRepo = new ContentRepository(); 
    $content = $contentRepo->store($request); 

    if($content->isValid()) { 
     $resource->content_id = $content->id; 

     $directory = 'frontend/videos/assets/'.date("Y").'/'.date('m').'/'.time(); 
     \File::makeDirectory($directory, 0755, true); 
     $request->video->move($directory.'/', $request->video->getClientOriginalName()); 
     $resource->video = '/'.$directory.'/'.$request->video->getClientOriginalName(); 
     $request->preview_image->move($directory.'/', $request->preview_image->getClientOriginalName()); 
     $resource->preview_image = '/'.$directory.'/'.$request->preview_image->getClientOriginalName(); 
     $resource->highlighted = intval($request->input('highlighted') == 'on'); 

     $resource->save(); 

     return $resource; 
    } 
    else { 
     return $content; 
    } 
} 

L'important est de garder l'appel $request->video->move() que je dois probablement remplacer afin d'utiliser Virtual Filesystem.

puis le test

public function testVideoUpload(){ 
     File::put(__DIR__.'/frontend/videos/assets/image.mp4', 'test'); 
     $file = new UploadedFile(__DIR__.'/frontend/videos/assets/image.mp4', 'foofile.mp4', 'video/mp4', 100023, null, $test=true); 

     File::put(__DIR__.'/frontend/images/assets/image.jpg', 'test'); 
     $preview = new UploadedFile(__DIR__.'/frontend/images/assets/image.jpg', 'foofile.jpg', 'image/jpeg', 100023, null, $test=true); 

     $this->post('/admin/videos', [ 
      'title' => 'My Video #12', 
      'description' => 'This is a description', 
      'actors' => [$this->actor->id, $this->actor2->id], 
      'scenes' => [$this->scene->id, $this->scene2->id], 
      'payment_methods' => [$this->paymentMethod->id], 
      'video' => $file, 
      'preview_image' => $preview 
     ])->seeInDatabase('contents', [ 
      'title' => 'My Video #12', 
      'description' => 'This is a description' 
     ]); 
} 

Comme vous pouvez le voir, je dois créer un fichier fictif dans un répertoire local et utiliser alors que dans la requête HTTP au point final de la forme, puis après, ce fichier serait déplacé et j'ai besoin de supprimer le dossier créé et le nouveau fichier déplacé ... c'est un gâchis authentique.

En tant que tel je veux utiliser Virtual Filesystem à la place, mais je ne sais pas comment le configurer dans ce cas particulier, j'ai déjà téléchargé un paquet et le configurer, mais les questions sont, d'abord, quel paquet avez-vous utilisé/recommandé et comment ajusteriez-vous la classe et le test pour supporter le système de fichiers virtuel? Aurais-je besoin de passer à l'utilisation de la façade de stockage au lieu de l'appel $request->video->move()? Si oui, comment cela se ferait-il exactement?

Merci d'avance pour votre aide

Répondre

1

Je ne pouvais pas comprendre le système VFS, mais je n'ai en quelque sorte une alternative qui est toujours un peu compliqué, mais fait le travail. Fondamentalement, j'ai mis en place deux méthodes sur ma classe de base PHPUnit pour installer et démonter les dossiers temporaires dont j'ai besoin sur tout test qui les nécessite, car j'utilise les transactions de base de données les fichiers sont supprimés à chaque test et je dois créer de nouveaux fichiers factices chaque fois que je lance le test.

J'ai donc deux méthodes setupTempDirectories et teardownTempDirectories que je vais appeler au début et à la fin de chaque test qui nécessite ces répertoires temporaires.

Je mis mes fichiers temporaires dans le répertoire de stockage parce que parfois je lance mes tests individuellement par PHPStorm et la commande __DIR__ obtient foiré et des points aux différents répertoires quand je fais ça, j'ai aussi essayé __FILE__ avec le même résultat, donc je juste eu recours à storage_path de Laravel à la place et cela fonctionne bien. Ensuite, cela laisse le problème de ma classe concrète qui essaie de déplacer les fichiers et de créer des répertoires dans le dossier public pour eux ... donc pour corriger que j'ai changé le code pour utiliser la façade de stockage, alors je Mock la façade de stockage dans mes tests

donc, dans ma classe concrète

 $directory = 'frontend/videos/assets/'.date("Y").'/'.date('m').'/'.time(); 
     Storage::makeDirectory($directory, 0755, true); 

     Storage::move($request->video, $directory . '/' . $request->video->getClientOriginalName()); 
     $resource->video = '/'.$directory.'/'.$request->video->getClientOriginalName(); 

     Storage::move($request->preview_image, $directory . '/' . $request->preview_image->getClientOriginalName()); 
     $resource->preview_image = '/'.$directory.'/'.$request->preview_image->getClientOriginalName(); 

et puis dans mon test je me moque à la fois les makeDirectory et les méthodes move comme telles

// Override the Storage facade with a Mock version so that we don't actually try to move files around... 
    Storage::shouldReceive('makeDirectory')->once()->andReturn(true); 
    Storage::shouldReceive('move')->twice()->andReturn(true); 

Cela fait que mes tests fonctionnent et ne laissent pas vraiment de fichiers après que ce soit fait ... J'espère que quelqu'un a une meilleure solution mais pour le moment c'est ce que j'ai imaginé. J'essayais en fait d'utiliser VFS mais cela n'a jamais fonctionné ... je continue d'obtenir des erreurs que le fichier original dans le répertoire storage n'est pas trouvé même si c'est juste là ...

Je ne suis même pas sûr que la façade de stockage utilise VFS en arrière-plan pour commencer, même si elle devrait ...