LadyC's avatar
Level 1

Laravel 5.6 - testing Post Request with Upload of image

Hi, I'm using Laravel 5.6 within XAMPP in a Windows 10 machine. I've written a Test Function for a Post Form which includes an image upload, taking as model this example written for Laravel 5.2.

Here is the function,

public function testUploadTodoWithImage()
    {
        $name = str_random(8).'.png';
        $path = 'C:\xampp\htdocs\todoapp\public\storage\image\'.$name;
        copy($this->uploadedFile, $path);
        $img = new UploadedFile($path, $name, 'image/png', filesize($path), null, true);
        $response = $this->actingAs($this->user)->call('POST','todo',
            [
                'todo' => 'Todo Title',
                'category' => 'Todo Category',
                'description' => 'Todo Description',
                'user_id' => $this->user->id,
                'image' => $name,
            ],
            [],
            ['photo' => $img],
            ['Accept' => 'application/json']
        );
        $response->assertStatus(200);

        $this->assertFileExists('C:\xampp\htdocs\todoapp\storage\app\public\image\'.$name);
    }

The thing is that I'm not sure if the logic is correct! I'm putting a file from the outside and checking if it's there in the folder structure… while that file should pass from the function that has to be tested …

Actually I wanted to try as it is shown in the documentation and also here, but I receive the error:

Unable to find a file at path [myimg.png]

Any ideas why?

Thanks in advance for your precious tips!

0 likes
2 replies
LadyC's avatar
LadyC
OP
Best Answer
Level 1

Hi guys, I went some steps ahead and find a draft solution.

Here the code:

public function testTodoWithImageUpload()
    {
        Storage::fake('images');

        $this->actingAs($this->user)->json('POST', '/todo', [
            'todo' => 'Todo Title',
            'category' => 'Todo Category',
            'description' => 'Todo Description',
            'user_id' => $this->user->id,
            'image' => UploadedFile::fake()->image('avatar.jpg')
        ]);

        Storage::disk('images')->assertExists('image/'.$_SESSION['testing']);
    }

In phpunit.xml

<env name="FILESYSTEM_DRIVER" value="images"/>

Basically I noticed that it had create a folder in storage/framework/testing/images/image/ where it was saving the testing image. The problem was to find the correct path and filename for the final assertExists.

My method that handles the storage is implemented in a way, that it changes the name of file (generating an hashName) and stores it in a subfolder named "image".

So I added the subfolder name in the assertExists and passed the hashName in a session variable (see the code above).

Here is the code of the function in charge of the Todo storage:


public function handleStoreTodo($request)
    {
        $parameters=$request->all();
        
        $parameters['image'] = ( null !== $request->file('image'))
                    ? $request->file('image')->store('image')
                    : 'not-set';

        $_SESSION['testing'] = $request->file('image')->hashName();
        $parameters['user_id'] = Auth::user()->id;
        $todo = $this->todo_rep->create($parameters);

        return $todo;
    }

Obviously is not yet a good solution, because I don't want to leave this $_SESSION variable usage there: I don't need it for production purpose (just for testing). So the question is: how do I get the hashName of the file in the testing function?

Thanks a lot for help! :)

1 like
hmreumann's avatar

Hallo, In my controller I used the path() method:

    $storagePath = Storage::disk('attachments')->path('/'.$attachment);

and in the Test I just used:

    $response = $this->actingAs(User::factory()->create())
    ->get('/attachments/'.$filenamestored);

    $response->assertOk();

Please or to participate in this conversation.