Bonjour,

Voila je rencontre un petit problème avec mon code.

Ce que je fais

Je teste la soupression d'un fichier attaché lorsque on souprime le contenu parant (Post, Pages, Project etc)

public function testDeleteAttachmentDeleteFile()
    {
        $response = $this->callController();
        $attachment = $response->json();
        $this->assertFileExists($this->getFileForAttachment($attachment));
        Attachment::find($attachment['id'])->delete();
        $this->assertFileNotExists($this->getFileForAttachment($attachment));
    }

    public function testDeletePostDeleteAllAttachments() {
        $response = $this->callController();
        $attachment = $response->json();
        factory(Attachment::class, 3)->create();
        $this->assertFileExists($this->getFileForAttachment($attachment));
        $this->assertEquals(4, Attachment::count());
        Project::first()->delete();
        $this->assertFileNotExists($this->getFileForAttachment($attachment));
        $this->assertEquals(3, Attachment::count());
    }

Ce que je veux

Le fichier dans le répectoire de test dans ce cas il est dans uploads/project/1/sdsdsadd.jpeg sois bien éffacé.

Ce que j'obtiens

Quand je lance les testes j'ai ces erreurs qui s'affiche :

...EFI                                                              6 / 6 (100%)

Time: 1.73 seconds, Memory: 22.00MB

There was 1 error:

1) Tests\Feature\AttachmentTest::testDeleteAttachmentDeleteFile
ErrorException: Array to string conversion

/var/www/sitesdev.test/lakamark/app/Attachment.php:48
/var/www/sitesdev.test/lakamark/app/Attachment.php:19
/var/www/sitesdev.test/lakamark/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:350
/var/www/sitesdev.test/lakamark/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:200
/var/www/sitesdev.test/lakamark/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:173
/var/www/sitesdev.test/lakamark/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php:148
/var/www/sitesdev.test/lakamark/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:790
/var/www/sitesdev.test/lakamark/tests/Feature/AttachmentTest.php:97

--

There was 1 failure:

1) Tests\Feature\AttachmentTest::testDeletePostDeleteAllAttachments
Failed asserting that file "/var/www/sitesdev.test/lakamark/public/uploads/project/1/lmFlAWFCBblgsyfW77TTSkIVvjvlBkWiTospKXiT.jpeg" does not exist.

/var/www/sitesdev.test/lakamark/tests/Feature/AttachmentTest.php:109

ERRORS!
Tests: 6, Assertions: 13, Errors: 1, Failures: 1, Incomplete: 1.

Dans mes test j'ai une fonction helper qui permet de réupéré les attributs d'un attachment particulier et d'appeler le controller :

/**
     * @param $attachment
     * @return string
     */
    public function getFileForAttachment($attachment) {
        $stringName = explode('\\', $attachment['attachable_type']);
        $prefix = lcfirst($stringName[1]);
        $final = dirname(dirname(__DIR__)) . '/public/uploads/' . $prefix.'/' . $attachment['attachable_id'] . '/' . $attachment['name'];
        return $final;
    }

    // appelle le controller 
     /**
     * @param array $data
     * @return \Illuminate\Foundation\Testing\TestResponse
     */
    private function callController($data = []) {
        $user = $this->createAUser();
        $this->be($user);
        $path = dirname(__DIR__) . '/fixtures/demo.jpg';
        $file = new UploadedFile($path, 'demo.jpg', filesize($path), 'image/jpeg', null, true);
        $project = Project::create(['name' => 'demo', 'content' => 'demo', 'draft' => 0, 'published' => 1]);
        $default = [
            'attachable_type' => Project::class,
            'attachable_id' => $project->id,
            'image' => $file,
            'user_id' => $user->id
        ];
        return $this->post(route('cloud.attachments.store'), array_merge($default, $data));
    }

Dans mon model Attachment j'ai des propriété suivante :

public static function boot()
    {
        parent::boot();
        self::deleted(function($attachment){
            $attachment->deleteFile($attachment);
        });
    }

/**
     * Upload a file
     * @param string $destination
     * @param UploadedFile $file
     * @return $this
     */
    public function uploadFile(string $destination, UploadedFile $file)
    {
        $file = $file->storePublicly($destination, ['disk' => 'public']);
        $this->name = basename($file);
        return $this;
    }

    public function deleteFile()
    {
        $type = explode('\\', $this->attachable_type);
        Storage::disk('public')->delete(public_path(). 'uploads/' . $type . $this->name);
    }

    /**
    Generate an url :
    eg. uploads/project/1/my_file.jpeg
    **/
    public function getUrlAttribute()
    {
        $type = explode('\\', $this->attachable_type);
        $url = '/uploads/'. lcfirst($type[1]) . '/' . $this->id . '/'. $this->name;
        return Storage::disk('public')->url($url);
    }

Dans le trait que j'ajoute au model où il va le comportement des fichiers attaché :

public static function bootAttachableConcern () {
        self::deleted(function ($subject) {
            foreach($subject->attachments()->get() as $attachment) {
                $attachment->deleteFile();
            }
            $subject->attachments()->delete();
        });

    }

    public function attachments(){
        return $this->morphMany(Attachment::class, 'attachable');
    }

Je sais pas d'où vient cette erreur. Merci de votre aide en avance.

5 réponses


lakamark
Auteur
Réponse acceptée

Finalement, j'avais mal nomé mon fichier AttachableConcern.php. Celui-ci était j'amais apellé. Mon système entièrement testé. Je suis certain de son fonctionement. Merci pour vos réponse. Je ferme le sujet.

Regarde comment mocker ta facade storage, sa devraity résoudre ton problème

Doc Laravel

C'est plutôt du côté de la façade File qu'il faut regarder. Il suffit dans le genre :

use Illuminate\Support\Facades\File;

...

File::delete(app_path('tests/'.$path));
lakamark
Auteur

Bonjour,
Désolé, de vous faire attendre. J'ai réssuit à réglé une partie du problème. Le teste testDeleteAttachmentDeleteFile() où j'ai eu une erreur "Array to string conviction" c'est réglé. Par contre le deuxième teste testDeleteProjectDeleteAllAttachments() Vérifie dès que le contenu parent (Post, page, video, etc) est surpprimer supprime les attachments et surprime les fichiers. J'ai cette erreur :

PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

....FI                                                              6 / 6 (100%)

Time: 2.85 seconds, Memory: 22.00MB

There was 1 failure:

1) Tests\Feature\AttachmentTest::testDeleteProjectDeleteAllAttachments
Failed asserting that file "/var/www/sitesdev.test/lakamark/public/uploads/project/1/uqzAm0vOXDn8jDKsSaPPRNh3alNbP2E4Y4i2b6QS.jpeg" does not exist.

/var/www/sitesdev.test/lakamark/tests/Feature/AttachmentTest.php:108

FAILURES!
Tests: 6, Assertions: 14, Failures: 1, Incomplete: 1.

Je voi t que le répectoire demandé existe bien dans le dossier uploads :

![](https://image.prntscr.com/image/rh6RgQA7RrGROCRxJntSFQ.png

J'ai fait un peut de "refactory" dans mon model Attachment j'ai faite une fonction qui génére le chemain ou le fichier va être télécharger.

 /**
     * Generate a directory in public folder :
     * /public/uploads/example/1/your_file.jpg
     * @return string
     */
    private function generateDirectory()
    {
        $model = explode("\\", $this->attachable_type);
        $id = $this->attachable_id;
        $ds = DIRECTORY_SEPARATOR;
        $url = 'uploads' . $ds . lcfirst($model[1]) . $ds . $id . $ds;
        return $url;
    }

Ensuite dans mes autre fonction j'ai fait ceci:

/**
     * Upload a file
     * @param UploadedFile $file
     * @return $this
     */
    public function uploadFile(UploadedFile $file)
    {
        $path = $this->generateDirectory();
        $file = $file->storePublicly($path, ['disk' => 'public']);
        $this->name = basename($file);
        return $this;
    }

    public function getUrlAttribute()
    {
        $url = $this->generateDirectory() . $this->name;
        return Storage::disk('public')->url($url);
    }

    public function deleteFile()
    {
        $url = $this->generateDirectory() . $this->name;
        Storage::disk('public')->delete($url);
    }

Quand je debug ma fonction deleteFile() ça me retourne le bon chemain :

PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

..."uploads/project/1/KzBYgh6NBDrLYgV5jGQdgsBB1Ckyc6mpPQPzsMmQ.jpeg"

Pourquoi qu'il ne réussit pas à trouver le fichier? J'utilise cette fonction generateDirectory() quand je téléverse (upload) le fichier. Tout mes autre tests passe au vert sauf celui-ci.

Merci de vos répone.

lakamark
Auteur

J'ai débuguer ma fonction qui soccupe de supprimer un fichier la fonction deleteFile() Je vois bien le fichier est bien effacer dans la répectoire :

Avant :

Après :

Je ne vois pas pourquoi le teste ne passe pas. Ça me dit toujours test échoué. Je ne comprend pas d'où viens le problème.