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

时间:2015-10-22 12:57:27

标签: php laravel phpunit

我正在尝试在我的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);
}

但控制器未通过此检查:

elseif (!Input::hasFile('file'))
{
    return Response::error('No file uploaded');
}

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

更新

根据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();
}

但没有成功。使用的文件存在且大小正确。

6 个答案:

答案 0 :(得分:10)

Docs for CrawlerTrait.html#method_action读到:

  

参数
  string $ method
  string $ action
  array $ wildcards
  数组$参数
  array $ cookies
  数组$文件
  array $ server
  string $ content

所以我认为正确的电话应该是

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<script src="../Scripts/jquery-1.4.1.min.js"></script>
<script type="text/javascript">
    $('#type_').change(function () {
    if (this.value == 'other') {
        $('#other_type').css('display', 'block');
    }
    else {
        $('#other_type').css('display', 'none');
    }
});
</script>
<div>
    <asp:Label ID="Label1" runat="server" Text="Type : "></asp:Label>
    <asp:DropDownList ID="type_" runat="server"  style="margin-left: 0px">
        <asp:ListItem>a</asp:ListItem>
        <asp:ListItem>b</asp:ListItem>
        <asp:ListItem>c</asp:ListItem>
        <asp:ListItem>other</asp:ListItem>
    </asp:DropDownList>
    <asp:TextBox ID="other_type" runat="server" style="margin-left: 33px; display:none"  Width="157px"></asp:TextBox>.......

除非它需要非空的通配符和cookie。

作为旁注,它绝不是单位测试。

答案 1 :(得分:6)

对于任何绊倒这个问题的人,你现在可以这样做:

    $response = $this->postJson('/product-import', [
        'file' => new \Illuminate\Http\UploadedFile(resource_path('test-files/large-avatar.jpg'), 'large-avatar.jpg', null, null, null, true),
    ]);

答案 2 :(得分:5)

使用phpunit,您可以使用attach()方法将文件附加到表单。

来自lumen docs的示例:

public function testPhotoCanBeUploaded()
{
    $this->visit('/upload')
         ->name('File Name', 'name')
         ->attach($absolutePathToFile, 'photo')
         ->press('Upload')
         ->see('Upload Successful!');
}

答案 3 :(得分:3)

以下是如何使用自定义文件进行测试的完整示例。我需要这个来解析具有已知格式的CSV文件,因此我的文件必须具有精确的格式和内容。如果您只需要图像或随机大小的文件,请使用$ file-&gt; fake-&gt; 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');
    }
}

这是控制器:

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

答案 4 :(得分:2)

首先导入必要的东西

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

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

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

然后创建一个JSON数据以传递文件。例子

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

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

$user = User::where('email','candidate@gmail.com')->first();

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

$response->assertStatus(200);

我希望它能起作用。

答案 5 :(得分:1)

在您的测试用例中添加类似的DELETE FROM TABLE_A WHERE TABLE_A IN(SELECT ID FROM TABLE_B) 方法:

setUp()

这会欺骗你的$ _FILES全球,让Laravel认为上传了一些内容。