Devin Norgarb
Devin Norgarb

Reputation: 1159

How to test in PHPUnit; a CSV File Upload using an API written in Laravel?

I would like to upload a CSV file via a Laravel API then test the upload with PHPUnit.

What would my store() function in the Controller and testCreate() function basically look like.

This is what I got so far:

<?php

use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\WithoutMiddleware;

class ProspectListControllerTest extends TestCase
{

use WithoutMiddleware, DatabaseTransactions;

public function testCreate()
{

    $file = new Symfony\Component\HttpFoundation\File\UploadedFile(storage_path('/crm/data/test-file.csv'), 'test-file.csv', 'text/plain', 446, null, true);

    $this->call('POST', '/api/lists-imports/', [], [], ['csv_file' => $file]);
    $this->dump()->assertResponseOk();
  }
}

and the controller method looks like:

<?php

namespace App\Http\Controllers;

use App\ListImport;
use Illuminate\Http\Request;

class ListImportController extends Controller
{
public $model = ListImport::class;

public function store(Request $request, ListImport $importList)
{
    $request->file('importFile')->move(public_path('storage.crm.data'), $request->file('importFile')->getClientOriginalName());

    $importList->importFile = public_path('storage.crm.data') . '/' . $request->file('importFile')->getClientOriginalName();

    $importList->save();

}
}

Any help will be appreciated :)

Upvotes: 11

Views: 7482

Answers (3)

Tuan Nguyen
Tuan Nguyen

Reputation: 1

For new Laravel version. This is how I think you should write your test. More info inside: https://laravel.com/docs/9.x/http-tests#testing-file-uploads

Don't know why but I tried another way, test passed but the original file test-file.csv got deleted so I don't chose this answer.

use Illuminate\Http\UploadedFile;
use Symfony\Component\HttpFoundation\File\UploadedFile as SymfonyUploadedFile;

$file = new SymfonyUploadedFile(storage_path('/crm/data/test-file.csv'), 'test-file.csv', 'text/plain');
$newfile = UploadedFile::createFromBase($file, true);
$post = $this->post('/api/lists-imports/', [
    'file' => $newfile,
]);

My solution:

<?php

use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;
use Illuminate\Http\UploadedFile;

class ProspectListControllerTest extends TestCase
{
    use WithoutMiddleware, DatabaseTransactions;

    public function testCreate()
    {
        $file = fopen(storage_path('/crm/data/test-file.csv'), "r") or die("Unable to open file!");
        $fileContent = fread($file, filesize(storage_path('/crm/data/test-file.csv')));
        fclose($file);
        $file = UploadedFile::fake()->createWithContent(
            'test-file.csv', $fileContent
        );
        $post = $this->post('/api/lists-imports/', [
            'file' => $file,
        ]);
        // Your assertions
    }
}

Upvotes: 0

Matt Holmes
Matt Holmes

Reputation: 961

Here's an example of my feature test Laravel 6 and higher ('uploads' is my storage driver):

    use Illuminate\Http\UploadedFile;

    Storage::fake('uploads');

    $header = 'Header 1,Header 2,Header 3';
    $row1 = 'value 1,value 2,value 3';
    $row2 = 'value 1,value 2,value 3';

    $content = implode("\n", [$header, $row1, $row2]);

    $inputs = [
        'csv_file' =>
            UploadedFile::
                fake()->
                createWithContent(
                    'test.csv',
                    $content
                )
    ];


    $response = $this->postJson(
        'file-upload',
        $inputs

    );

    $response->assertOk();

Upvotes: 9

Christoph
Christoph

Reputation: 1

There is a new way of testing file uploads in Laravel. https://laravel-news.com/testing-file-uploads-with-laravel

It is like this: (from the docs)

   public function testAvatarUpload()
{
    Storage::fake('avatars');

    $response = $this->json('POST', '/avatar', [
        'avatar' => UploadedFile::fake()->image('avatar.jpg')
    ]);

    // Assert the file was stored...
    Storage::disk('avatars')->assertExists('avatar.jpg');

    // Assert a file does not exist...
    Storage::disk('avatars')->assertMissing('missing.jpg');
}

Upvotes: -2

Related Questions