Reputation: 1159
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
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
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
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