I'm trying to run this functional test on my laravel controller. I would like to test image processing, but to do so I want to fake image uploading. How do I do this? I found a few examples online but none seem to work for me. Here's what I have:
我正试图在我的laravel控制器上运行这个功能测试。我想测试图像处理,但这样做我想伪造图像上传。我该怎么做呢?我在网上找到了一些例子,但似乎没有一个适合我。这就是我所拥有的:
public function testResizeMethod()
{
$this->prepareCleanDB();
$this->_createAccessableCompany();
$local_file = __DIR__ . '/test-files/large-avatar.jpg';
$uploadedFile = new Symfony\Component\HttpFoundation\File\UploadedFile(
$local_file,
'large-avatar.jpg',
'image/jpeg',
null,
null,
true
);
$values = array(
'company_id' => $this->company->id
);
$response = $this->action(
'POST',
'FileStorageController@store',
$values,
['file' => $uploadedFile]
);
$readable_response = $this->getReadableResponseObject($response);
}
But the controller doesn't get passed this check:
但是控制器没有通过这个检查:
elseif (!Input::hasFile('file'))
{
return Response::error('No file uploaded');
}
So somehow the file isn't passed correctly. How do I go about this?
所以文件不能正确传递。我该怎么做?
Update
Based on max.lanin's suggestin, I also tried:
基于max.lanin的建议,我也尝试过:
public function setUp()
{
// Tried with parent::setUp() here and at the end
// parent::setUp();
$local_file = __DIR__ . '/test-files/large-avatar.jpg';
print($local_file);
$_FILES = array(
'file' => array (
'tmp_name' => $local_file,
'name' => 'large-avatar.jpg',
'type' => 'image/jpeg',
'size' => 335057,
'error' => 0,
),
'image' => array (
'tmp_name' => $local_file,
'name' => 'large-avatar.jpg',
'type' => 'image/jpeg',
'size' => 335057,
'error' => 0,
),
);
parent::setUp();
}
but without succes. The file used exists and the size is correct.
但没有成功。使用的文件存在且大小正确。
5 个解决方案
#1
9
Docs for CrawlerTrait.html#method_action reads:
CrawlerTrait.html#method_action的文档内容如下:
Parameters
string $method
string $action
array $wildcards
array $parameters
array $cookies
array $files
array $server
string $content参数string $ method string $ action array $ wildcards array $ parameters array $ cookies array $ files array $ server string $ content
So I assume the correct call should be
所以我认为正确的呼叫应该是
$response = $this->action(
'POST',
'FileStorageController@store',
[],
$values,
[],
['file' => $uploadedFile]
);
unless it requires non-empty wildcards and cookies.
除非它需要非空的通配符和cookie。
As a side note, it is by no means a unit test.
作为旁注,它绝不是单元测试。
#2
4
With phpunit you can attach a file to a form by using attach() method.
使用phpunit,您可以使用attach()方法将文件附加到表单。
Example from lumen docs:
流明文档示例:
public function testPhotoCanBeUploaded()
{
$this->visit('/upload')
->name('File Name', 'name')
->attach($absolutePathToFile, 'photo')
->press('Upload')
->see('Upload Successful!');
}
#3
4
For anyone else stumbling upon this question, you can nowadays do this:
对于任何绊倒这个问题的人,你现在可以这样做:
$response = $this->postJson('/product-import', [
'file' => new \Illuminate\Http\UploadedFile(resource_path('test-files/large-avatar.jpg'), 'large-avatar.jpg', null, null, null, true),
]);
#4
0
Add similar setUp()
method into your testcase:
将类似的setUp()方法添加到您的测试用例中:
protected function setUp()
{
parent::setUp();
$_FILES = array(
'image' => array(
'name' => 'test.jpg',
'tmp_name' => __DIR__ . '/_files/phpunit-test.jpg',
'type' => 'image/jpeg',
'size' => 499,
'error' => 0
)
);
}
This will spoof your $_FILES global and let Laravel think that there is something uploaded.
这会欺骗你的$ _FILES全局,让Laravel认为上传了一些内容。
#5
0
Here is a full example how to test with custom files. I needed this for parsing CSV files with known format so my files had to had exact formatting and contents. If you need just images or random sized files use $file->fake->image() or create() methods. Those come bundled with Laravel.
以下是如何使用自定义文件进行测试的完整示例。我需要这个来解析具有已知格式的CSV文件,因此我的文件必须具有精确的格式和内容。如果您只需要图像或随机大小的文件,请使用$ file-> fake-> image()或create()方法。那些与Laravel捆绑在一起。
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
class PanelistImportTest extends TestCase
{
/** @test */
public function user_should_be_able_to_upload_csv_file()
{
// If your route requires authenticated user
$user = Factory('App\User')->create();
$this->actingAs($user);
// Fake any disk here
Storage::fake('local');
$filePath='/tmp/randomstring.csv';
// Create file
file_put_contents($filePath, "HeaderA,HeaderB,HeaderC\n");
$this->postJson('/upload', [
'file' => new UploadedFile($filePath,'test.csv', null, null, null, true),
])->assertStatus(200);
Storage::disk('local')->assertExists('test.csv');
}
}
Here is the controller to go with it:
这是控制器:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage;
class UploadController extends Controller
{
public function save(Request $request)
{
$file = $request->file('file');
Storage::disk('local')->putFileAs('', $file, $file->getClientOriginalName());
return response([
'message' => 'uploaded'
], 200);
}
}
#1
9
Docs for CrawlerTrait.html#method_action reads:
CrawlerTrait.html#method_action的文档内容如下:
Parameters
string $method
string $action
array $wildcards
array $parameters
array $cookies
array $files
array $server
string $content参数string $ method string $ action array $ wildcards array $ parameters array $ cookies array $ files array $ server string $ content
So I assume the correct call should be
所以我认为正确的呼叫应该是
$response = $this->action(
'POST',
'FileStorageController@store',
[],
$values,
[],
['file' => $uploadedFile]
);
unless it requires non-empty wildcards and cookies.
除非它需要非空的通配符和cookie。
As a side note, it is by no means a unit test.
作为旁注,它绝不是单元测试。
#2
4
With phpunit you can attach a file to a form by using attach() method.
使用phpunit,您可以使用attach()方法将文件附加到表单。
Example from lumen docs:
流明文档示例:
public function testPhotoCanBeUploaded()
{
$this->visit('/upload')
->name('File Name', 'name')
->attach($absolutePathToFile, 'photo')
->press('Upload')
->see('Upload Successful!');
}
#3
4
For anyone else stumbling upon this question, you can nowadays do this:
对于任何绊倒这个问题的人,你现在可以这样做:
$response = $this->postJson('/product-import', [
'file' => new \Illuminate\Http\UploadedFile(resource_path('test-files/large-avatar.jpg'), 'large-avatar.jpg', null, null, null, true),
]);
#4
0
Add similar setUp()
method into your testcase:
将类似的setUp()方法添加到您的测试用例中:
protected function setUp()
{
parent::setUp();
$_FILES = array(
'image' => array(
'name' => 'test.jpg',
'tmp_name' => __DIR__ . '/_files/phpunit-test.jpg',
'type' => 'image/jpeg',
'size' => 499,
'error' => 0
)
);
}
This will spoof your $_FILES global and let Laravel think that there is something uploaded.
这会欺骗你的$ _FILES全局,让Laravel认为上传了一些内容。
#5
0
Here is a full example how to test with custom files. I needed this for parsing CSV files with known format so my files had to had exact formatting and contents. If you need just images or random sized files use $file->fake->image() or create() methods. Those come bundled with Laravel.
以下是如何使用自定义文件进行测试的完整示例。我需要这个来解析具有已知格式的CSV文件,因此我的文件必须具有精确的格式和内容。如果您只需要图像或随机大小的文件,请使用$ file-> fake-> image()或create()方法。那些与Laravel捆绑在一起。
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
class PanelistImportTest extends TestCase
{
/** @test */
public function user_should_be_able_to_upload_csv_file()
{
// If your route requires authenticated user
$user = Factory('App\User')->create();
$this->actingAs($user);
// Fake any disk here
Storage::fake('local');
$filePath='/tmp/randomstring.csv';
// Create file
file_put_contents($filePath, "HeaderA,HeaderB,HeaderC\n");
$this->postJson('/upload', [
'file' => new UploadedFile($filePath,'test.csv', null, null, null, true),
])->assertStatus(200);
Storage::disk('local')->assertExists('test.csv');
}
}
Here is the controller to go with it:
这是控制器:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage;
class UploadController extends Controller
{
public function save(Request $request)
{
$file = $request->file('file');
Storage::disk('local')->putFileAs('', $file, $file->getClientOriginalName());
return response([
'message' => 'uploaded'
], 200);
}
}