laravel 如何使用laravel和phpunit测试文件上传?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33281614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 12:33:27  来源:igfitidea点击:

How to test file upload with laravel and phpunit?

phplaravelphpunit

提问by Jasper Kennis

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?

所以不知何故文件没有正确传递。我该怎么做?

采纳答案by Alex Blex

Docs for CrawlerTrait.html#method_actionreads:

CrawlerTrait.html#method_action 的文档如下:

Parameters
string $method
string $action
array $wildcards
array $parameters
array $cookies
array $files
array $server
string $content

参数
字符串 $method
字符串 $action
数组 $wildcards
数组 $parameters
数组 $cookies
数组 $files
数组 $server
字符串 $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。

回答by Mikael

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),
    ]);

回答by Alex Kyriakidis

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!');
}

回答by Juha Vehnia

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);
    }
}

回答by Inamur Rahman

The best and Easiest way :First Import the Necessary things

最好最简单的方法:首先导入必要的东西

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

Then make a fake file to upload.

然后制作一个假文件上传。

Storage::fake('local');
$file = UploadedFile::fake()->create('file.pdf');

Then make a JSON Data to pass the file. Example

然后制作一个 JSON 数据来传递文件。例子

$parameters =[
            'institute'=>'Allen Peter Institute',
            'total_marks'=>'100',
            'aggregate_marks'=>'78',
            'percentage'=>'78',
            'year'=>'2002',
            'qualification_document'=>$file,
        ];

Then send the Data to your API.

然后将数据发送到您的 API。

$user = User::where('email','[email protected]')->first();

$response = $this->json('post', 'api/user', $parameters, $this->headers($user));

$response->assertStatus(200);

I hope it will work.

我希望它会起作用。

回答by Maxim Lanin

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 认为有东西上传了。