I have the exact same problem, is the same if using submitForm(...) or attach(...).
have you solved it?
Hello,
I have create a test project to upload a file it is working when i use a browser but when i try to execute a test it doesn't.
I have an error when i try to move the file :
Caused by
exception 'Symfony\Component\HttpFoundation\File\Exception\FileException' with message 'The file "photo.JPG" was not uploaded due to an unknown error.' in /Users/xxx/uploader/vendor/symfony/http-foundation/File/UploadedFile.php:251
Stack trace:
Do you have an idea why this fails with php unit ?
Here is the code for the test
/** @test */
public function it_can_upload_a_file()
{
//given
$test_file_path = base_path().'/tests/data/photo.JPG';
$this->assertTrue(file_exists($test_file_path), 'Test file does not exist');
$this->visit('/')
->attach($test_file_path,'archive-file')
->press('Upload')
->see('uploaded successfully');
}
The code in the controller
* Store a newly created resource in storage.
*
* @return Response
*/
public function store(Request $request)
{
//Get the uploaded file
$file = $request->file('archive-file');
//Move it to the final destination
$directory_path = public_path() . '/uploaded/';
$file->move($directory_path);
}
if i dd the $file in the controller, the file is correctly uploaded :
.Symfony\Component\HttpFoundation\File\UploadedFile {#346
-test: false
-originalName: "photo.JPG"
-mimeType: "application/octet-stream"
-size: 228530
-error: 0
}
I'm stuck ...
I have the exact same problem, is the same if using submitForm(...) or attach(...).
have you solved it?
No i haven't find a solution yet
The issue is in the UploadedFIle.php (Symfony\Component\HttpFoundation\File)
The method isValid returns false because the call to is_uploaded_file() always return false.
I have checked and the file is correctly uploaded and file_exists return true on the path of the file. I don't know why is_uploaded_file fails
I think is_uploaded_file() fails because the upload is not in the same HTTP request or something like that, also move_uploaded_file() fails for the same reason, that's why UploadedFile uses a $test flag.
The trick here is how to pass true to that flag from Laravel when runnin in testing env?
Or maybe there is something wrong with Laravel when make the HTTP request with attachments on testing env?
It's very weird that Laravel offers this methods to attach files and they don't work... and I think it never worked before with the new integration testing.
So... any clues? Don't let this topic die, we need a solution.
What is the complete stacktrace of the exception?
Here is the complete stack
PHPUnit 4.7.6 by Sebastian Bergmann and contributors.
.F
Time: 341 ms, Memory: 14.25Mb
There was 1 failure:
1) ExampleTest::it_can_upload_a_file
A request to [http://uploader.dev] failed. Received status code [500].
/Users/user/uploader/vendor/laravel/framework/src/Illuminate/Foundation/Testing/CrawlerTrait.php:230
/Users/user/uploader/vendor/laravel/framework/src/Illuminate/Foundation/Testing/CrawlerTrait.php:153
/Users/user/uploader/vendor/laravel/framework/src/Illuminate/Foundation/Testing/CrawlerTrait.php:172
/Users/user/uploader/vendor/laravel/framework/src/Illuminate/Foundation/Testing/CrawlerTrait.php:568
/Users/user/uploader/vendor/laravel/framework/src/Illuminate/Foundation/Testing/CrawlerTrait.php:556
/Users/user/uploader/tests/ExampleTest.php:34
Caused by
exception 'Symfony\Component\HttpFoundation\File\Exception\FileException' with message 'The file "photo.JPG" was not uploaded due to an unknown error.' in /Users/user/uploader/vendor/symfony/http-foundation/File/UploadedFile.php:254
Stack trace:
#0 /Users/user/uploader/app/Http/Controllers/Uploader.php(48): Symfony\Component\HttpFoundation\File\UploadedFile->move('/Users/user/u...')
#1 [internal function]: App\Http\Controllers\Uploader->store(Object(Illuminate\Http\Request))
#2 /Users/user/uploader/bootstrap/cache/compiled.php(8416): call_user_func_array(Array, Array)
#3 /Users/user/uploader/bootstrap/cache/compiled.php(8485): Illuminate\Routing\Controller->callAction('store', Array)
#4 /Users/user/uploader/bootstrap/cache/compiled.php(8465): Illuminate\Routing\ControllerDispatcher->call(Object(App\Http\Controllers\Uploader), Object(Illuminate\Routing\Route), 'store')
#5 [internal function]: Illuminate\Routing\ControllerDispatcher->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#6 /Users/user/uploader/bootstrap/cache/compiled.php(9122): call_user_func(Object(Closure), Object(Illuminate\Http\Request))
#7 [internal function]: Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#8 /Users/user/uploader/bootstrap/cache/compiled.php(9104): call_user_func(Object(Closure), Object(Illuminate\Http\Request))
#9 /Users/user/uploader/bootstrap/cache/compiled.php(8466): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#10 /Users/user/uploader/bootstrap/cache/compiled.php(8451): Illuminate\Routing\ControllerDispatcher->callWithinStack(Object(App\Http\Controllers\Uploader), Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request), 'store')
#11 /Users/user/uploader/bootstrap/cache/compiled.php(7426): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request), 'App\\Http\\Contro...', 'store')
#12 /Users/user/uploader/bootstrap/cache/compiled.php(7397): Illuminate\Routing\Route->runWithCustomDispatcher(Object(Illuminate\Http\Request))
#13 /Users/user/uploader/bootstrap/cache/compiled.php(7050): Illuminate\Routing\Route->run(Object(Illuminate\Http\Request))
#14 [internal function]: Illuminate\Routing\Router->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#15 /Users/user/uploader/bootstrap/cache/compiled.php(9122): call_user_func(Object(Closure), Object(Illuminate\Http\Request))
#16 [internal function]: Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#17 /Users/user/uploader/bootstrap/cache/compiled.php(9104): call_user_func(Object(Closure), Object(Illuminate\Http\Request))
#18 /Users/user/uploader/bootstrap/cache/compiled.php(7051): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#19 /Users/user/uploader/bootstrap/cache/compiled.php(7039): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#20 /Users/user/uploader/bootstrap/cache/compiled.php(7024): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#21 /Users/user/uploader/bootstrap/cache/compiled.php(2066): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#22 [internal function]: Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}(Object(Illuminate\Http\Request))
#23 /Users/user/uploader/bootstrap/cache/compiled.php(9122): call_user_func(Object(Closure), Object(Illuminate\Http\Request))
#24 /Users/user/uploader/bootstrap/cache/compiled.php(2686): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#25 [internal function]: Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->handle(Object(Illuminate\Http\Request), Object(Closure))
#26 /Users/user/uploader/bootstrap/cache/compiled.php(9114): call_user_func_array(Array, Array)
#27 /Users/user/uploader/bootstrap/cache/compiled.php(12370): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#28 [internal function]: Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#29 /Users/user/uploader/bootstrap/cache/compiled.php(9114): call_user_func_array(Array, Array)
#30 /Users/user/uploader/bootstrap/cache/compiled.php(11019): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#31 [internal function]: Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#32 /Users/user/uploader/bootstrap/cache/compiled.php(9114): call_user_func_array(Array, Array)
#33 /Users/user/uploader/bootstrap/cache/compiled.php(12108): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#34 [internal function]: Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#35 /Users/user/uploader/bootstrap/cache/compiled.php(9114): call_user_func_array(Array, Array)
#36 /Users/user/uploader/bootstrap/cache/compiled.php(12047): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#37 [internal function]: Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#38 /Users/user/uploader/bootstrap/cache/compiled.php(9114): call_user_func_array(Array, Array)
#39 /Users/user/uploader/bootstrap/cache/compiled.php(2736): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#40 [internal function]: Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
#41 /Users/user/uploader/bootstrap/cache/compiled.php(9114): call_user_func_array(Array, Array)
#42 [internal function]: Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#43 /Users/user/uploader/bootstrap/cache/compiled.php(9104): call_user_func(Object(Closure), Object(Illuminate\Http\Request))
#44 /Users/user/uploader/bootstrap/cache/compiled.php(2013): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#45 /Users/user/uploader/bootstrap/cache/compiled.php(1999): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#46 /Users/user/uploader/vendor/laravel/framework/src/Illuminate/Foundation/Testing/CrawlerTrait.php(682): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#47 /Users/user/uploader/vendor/laravel/framework/src/Illuminate/Foundation/Testing/CrawlerTrait.php(151): Illuminate\Foundation\Testing\TestCase->call('POST', 'http://uploader...', Array, Array, Array)
#48 /Users/user/uploader/vendor/laravel/framework/src/Illuminate/Foundation/Testing/CrawlerTrait.php(172): Illuminate\Foundation\Testing\TestCase->makeRequest('POST', 'http://uploader...', Array, Array, Array)
#49 /Users/user/uploader/vendor/laravel/framework/src/Illuminate/Foundation/Testing/CrawlerTrait.php(568): Illuminate\Foundation\Testing\TestCase->makeRequestUsingForm(Object(Symfony\Component\DomCrawler\Form))
#50 /Users/user/uploader/vendor/laravel/framework/src/Illuminate/Foundation/Testing/CrawlerTrait.php(556): Illuminate\Foundation\Testing\TestCase->submitForm('Upload', Array)
#51 /Users/user/uploader/tests/ExampleTest.php(34): Illuminate\Foundation\Testing\TestCase->press('Upload')
#52 [internal function]: ExampleTest->it_can_upload_a_file()
#53 /Users/user/uploader/vendor/phpunit/phpunit/src/Framework/TestCase.php(881): ReflectionMethod->invokeArgs(Object(ExampleTest), Array)
#54 /Users/user/uploader/vendor/phpunit/phpunit/src/Framework/TestCase.php(746): PHPUnit_Framework_TestCase->runTest()
#55 /Users/user/uploader/vendor/phpunit/phpunit/src/Framework/TestResult.php(601): PHPUnit_Framework_TestCase->runBare()
#56 /Users/user/uploader/vendor/phpunit/phpunit/src/Framework/TestCase.php(702): PHPUnit_Framework_TestResult->run(Object(ExampleTest))
#57 /Users/user/uploader/vendor/phpunit/phpunit/src/Framework/TestSuite.php(738): PHPUnit_Framework_TestCase->run(Object(PHPUnit_Framework_TestResult))
#58 /Users/user/uploader/vendor/phpunit/phpunit/src/Framework/TestSuite.php(738): PHPUnit_Framework_TestSuite->run(Object(PHPUnit_Framework_TestResult))
#59 /Users/user/uploader/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(428): PHPUnit_Framework_TestSuite->run(Object(PHPUnit_Framework_TestResult))
#60 /Users/user/uploader/vendor/phpunit/phpunit/src/TextUI/Command.php(147): PHPUnit_TextUI_TestRunner->doRun(Object(PHPUnit_Framework_TestSuite), Array)
#61 /Users/user/uploader/vendor/phpunit/phpunit/src/TextUI/Command.php(99): PHPUnit_TextUI_Command->run(Array, true)
#62 /Users/user/uploader/vendor/phpunit/phpunit/phpunit(36): PHPUnit_TextUI_Command::main()
#63 {main}
FAILURES!
Tests: 2, Assertions: 5, Failures: 1.
anybody has a clue about this ?
Nope, I think @luceos is on it?
is debug on?
and what is the output of php artisan --version?
Seems like Laravel builds the request files through Symfony and Symfony knows nothing about testing. It's very difficult to debug I ran on solid ground when getting to:
vendor/symfony/http-foundation/Request.php:1975
private static function createRequestFromFactory(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
{
if (self::$requestFactory) {
$request = call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content);
if (!$request instanceof Request) {
throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.');
}
return $request;
}
return new static($query, $request, $attributes, $cookies, $files, $server, $content);
}
I'm running on laravel 5.1.6 with debug mode on
❯ php artisan --version [12:57:07]
Laravel Framework version 5.1.6 (LTS)
I have reproduced this on a fresh project if you like i can share it.
Hi guys, any updates?
new UploadedFile($file, 'file', null, null, null, true);
Solution: Add true to the 6th parameter.
the last parameter indicates whether it is a test file. If this is true, then it will fix your problems, as it skips the validity check.
Hi Guys,
I came across a similar problem while trying to test uploading a file on a form. Here is what I have done to make it work :
// Put this function in a helpers.php or a class (can be called statically) or anywhere you like
function prepareFileUpload($path)
{
TestCase::assertFileExists($path);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path);
return new \Symfony\Component\HttpFoundation\File\UploadedFile ($path, null, $mime, null, null, true);
}
//In your test file :
// Fill up your form array
$form = $this->someFakeData()
$form['file'] = prepareFileUpload('public/upload/file.pdf');
$this->visit($myUrl)->submitForm('Submit', $form);
//... Continue your checks .. see(), assert(), etc..
However if you typically have the following rule in your validator:
//...
'file' => 'mimes:pdf',
//...
You will get an error in these terms : file must be of one these types: pdf
This is because the above rule checks against the mimeType sent by the browser (which is not a terribly good practice) and the PHPUnit crawler always sends a mime type of 'application/octet-stream' and then laravel winges.
So to make the server check itself the mimeType and not rely on the browser, we have to define a custom validator rule:
class AppServiceProvider extends ServiceProvider {
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Validator::extend('is_pdf', function($attribute, $value, $parameters, $validator) {
$mime = \Request::file($attribute)->getMimeType();
return $mime == 'application/pdf';
});
}
//....
You should also define a custom error message, it is explained in the Laravel Doc (link above).
Then change your rule to :
'file' => 'is_pdf',
This example is hardcoded for the pdf case but I believe it should work for any type of file provided you change your custom validator accordingly.
This probably doesn't solve OP problem, but in latest Laravel 5.2 versions make sure you create object of
\Illuminate\Http\UploadedFile
and not
\Symfony\Component\HttpFoundation\File\UploadedFile
Otherwise you might get quite strange errors as for example with this mimes rule validation failure. There's no point to create any custom validation rules as @Mehdi_Souihed mentioned in his post. For explanation have a look at http://stackoverflow.com/questions/36857800/laravel-5-2-testing-uploadedfile-misses-the-test-value-after-post-bug
I posted a possible answer in stack overflow http://stackoverflow.com/a/37816191/1614842
Please or to participate in this conversation.