Behzadsh
Behzadsh

Reputation: 870

Testing file upload in lumen 5.5

I'm using Lumen 5.5, and I wrote simple app that upload files.

I wrote test like this (following this tutorial)

<?php

class UploadImageTest extends TestCase
{

    Use DatabaseMigrations;

    public function testUploadingImageSuccessfully()
    {
        $this->json('POST', '/images', [
            'image' => UploadedFile::fake()->image('image.jpg')
        ])->assertResponseOk()
    }

}

problem is that in my controller, $request->file('image') returns null.

<?php

use Illuminate\Http\Request;

class UploadController extends Controller
{

    public function upload(Request $request)
    {
        if ($request->file('image')) { // always return null
            return "File is uploaded!";
        }

        return "File is not uploaded!";
    }

}

I checked other questions (like this one) and tried given solutions with no luck!

Upvotes: 3

Views: 2211

Answers (3)

nur zazin
nur zazin

Reputation: 1188

this is working for me. just simple. this can submit file upload.

1.condition without authentication

5*1000 is file size (in KB). so i made a test with 5 MB file.

use Faker\Factory as Faker;
use Illuminate\Http\UploadedFile;

class SampleTest extends TestCase
{
    public function testItCanCreateUser()
    {
        $faker = Faker::create();
        $files = [
            'file' => UploadedFile::fake()->create('file.jpg', 5*1000)
        ];
        $response = $this->call('POST', '/chunk', [], [], $files);
        $this->assertEquals(200, $response->getStatusCode());
    }
}

2.condition with authentication (logged in user)

use Faker\Factory as Faker;
use Illuminate\Http\UploadedFile;

class SampleTest extends TestCase
{
    public function testItCanUpdateProfileUser()
    {
        $faker = Faker::create();
        $files = [
            'file' => UploadedFile::fake()->create('file.jpg', 5*1000)
        ];

        $headers = [
            'Accept' => 'application/json',
            'Authorization' => 'your-jwt-token'
        ];
        $servers = [];
        foreach ($headers as $k => $header) {
            $servers["HTTP_" . $k] = $header;
        }

        $response = $this->call('POST', '/chunk', [], [], $files, $servers);
        $this->assertEquals(200, $response->getStatusCode());
    }
}

you need to add HTTP_ on every request header. i'm not sure why. but it will work.

Upvotes: 1

Turbo
Turbo

Reputation: 688

Please note that passing file argument in the second argument of call() method does not work. Since the second argument is the payload data.

If you pass it as the data, when you use the command on the backend like this:

if($request->hasFile('my_file')) {
    // Do some logic here
}

$request->hasFile() will always return false.

You need to pass fake file upload in the 5th argument to make this works.

Here is the method signature of call

call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)

Upvotes: 1

bnunamak
bnunamak

Reputation: 674

I came across this question while searching for the answer to the same problem and wasn't sure it was related, so I posed one relevant to my use case. (Here)

The solution is simple: UploadedFile::fake() doesn't work with JSON, as it fakes a file upload with an XmlHttpRequest (as far as I can tell). You must therefore change your test from this:

public function testUploadingImageSuccessfully()
{
    $this->json('POST', '/images', [
        'image' => UploadedFile::fake()->image('image.jpg')
    ])->assertResponseOk()
}

to this:

public function testUploadingImageSuccessfully()
{
    $this->call('POST', '/images', [
        'image' => UploadedFile::fake()->image('image.jpg')
    ])->assertResponseOk()
}

Hope it helps!

Upvotes: 5

Related Questions