博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
组合使用Laravel和vfsStream测试文件上传
阅读量:6935 次
发布时间:2019-06-27

本文共 4946 字,大约阅读时间需要 16 分钟。

核心要点

\
  • 在应用开发中,测试是很重要的,在诸多的开发工具中,测试驱动开发是很伟大的一项; \
  • 测试文件上传并不像人们想象的那么简单; \
  • 目前,有很多很棒,但不为大家所熟知的测试工具; \
  • Larval能够让请求的校验更容易; \
  • 测试并不需要实际的文件系统,因为如果这样做的话,会在项目中引入添加/移除文件的代码,从而导致噪音的出现。

文件上传的测试可能会非常棘手,但是通过使用恰当的工具,再掌握一些技巧,这个过程可以会更加高效,也能更容易。\

如果你之前没有了解过的话,那么简单来讲,它允许与保存在内存中的文件进行交互,而不是与机器中实际存在文件进行交互。这样做的好处在于我们并不需要删除用于测试的文件,如果测试失败,teardown或者其他用于移除测试文件的代码没有执行,那么这就更会成为一个问题了。除此之外,因为它处理的是内存而不是物理的硬件驱动器,所以它会更快。简而言之,它能够更加整洁,速度也会更快。\

本文将会创建一个端点(路由)来上传包含用户信息的CSV文件,并测试CSV文件中的用户能够展现到一个JSON格式的响应中,同时还会添加校验功能,确保所处理的文件是CSV类型。这是一个超出现实的样例,不过它可以作为一个很好的起点,帮助你在项目中实现类似的功能。\

在本文中,我们假设你已经安装好了Laravel(我们所使用的是5.3版本)。你不用实际去点击这个路由,但是我们建议你使用或。在这个指南中,不会包含如何让它们就绪并运行起来的内容,通过这个仓库的中,你可以获取本文所对应的代码。\

起步

\

打开控制台并导航至项目的根文件夹(在这里你可以看到composer.json文件和.env文件等内容),如果你运行:

composer require mikey179/vfsStream --dev
\

那么就会将vfsStream拉取到composer file文件的development部分中,同时还会拉取所需的文件,从而能够在测试中使用这个包。完成这些之后,我们就为测试做好了准备。\

采用的TDD的方式编写代码

\

为了让这个过程尽可能简单,只需在tests文件夹(同样在项目的根目录下)中创建一个名为UploadCsvTest.php的文件。现在,我们需要打开这个文件并将如下的内容添加进去。

\u0026lt;?php\\class UploadCsvTest extends TestCase\{\    public function testSuccessfulUploadingCsv()\    {\\    }\\}
\

首先,我们让文件上传运行起来,然后可以再回过头来再添加校验功能。采取这种方式的原因在于,我们能够为可运行的代码迭代式地添加功能。例如,如果你能上传文件的话,那么它就是可运行的代码,为其添加校验是对功能的增强,可以稍后再进行。\

现在,添加如下的代码到“testSuccessfullUploadingCsv”函数中:

$this-\u0026gt;json('POST', 'upload-new-users-csv', ['usersCsvFile' =\u0026gt; 'someFile']);\$this-\u0026gt;assertResponseOk();
\

如果通过控制台运行(稍后,我们将会通过PHPUnit来引用这条命令)下面的命令的话:

phpunit --filter=UploadCsvTest
\

不出意料,这里会发生失败,看起来会像如下所示:

Expected status code 200, got 404.\Failed asserting that false is true.
\

404响应意味着无法找到路由,现在我们来定义它。导航至routes/web.php文件(从上一个Laravel版本开始,路由文件已经从Http目录转移到了这里),并且在文件的底部添加下面的代码:

Route::post('/upload-new-users-csv', function (\\Illuminate\\Http\\Request $request) {\\});
\

现在,如果我们运行PHPUnit的话,测试就能通过了。所以,接下来我们就应该在路由文件的闭包中访问预期的文件了。因此,回到这个文件中,并在闭包中添加如下这行代码:

$request-\u0026gt;input('usersCsvFile')-\u0026gt;openFile();
\

此时,路由看起来如下所示:

Route::post('/upload-new-users-csv', function (\\Illuminate\\Http\\Request $request) {\    $request-\u0026gt;input('usersCsvFile')-\u0026gt;openFile();\});
\

现在,如果你运行PHPUnit的话,会得到另外的错误,这是一个500错误。在这里,要查清发生了什么需要一点技巧。我们可以在测试中通过如下的方式来查看响应的内容:

dd($this-\u0026gt;response-\u0026gt;getContent());
\

但是很重要的一点在于,它要在断言响应OK之前执行,否则的话,在我们得到dd输出之前,测试就已经失败了。另外一种方式就是查看位于“storage/logs/laravel.log”中的日志。不管采用哪种检查方式,我们都会看到类似于这样的信息:“使用字符串的形式调用了成员函数openFile()”,这其实就是我们要达到的效果,因为在测试中,当我们发起post请求时,发送的是一个字符串。接下来,该看一下vfs了!\

熟悉vfsStream

\

它并不全面,但这是一个好的开端,这是一个非常深入和强大的包。为了让测试看起来更棒一些,我们先将创建文件的内容放到一个函数中。所以,回到测试文件(UploadCsvTest.php)中,将其修改成如下所示:

\u0026lt;?php \\use Illuminate\\Http\\UploadedFile;\use org\\bovigo\\vfs\\vfsStream;\\class UploadCsvTest extends TestCase\{\    public function testSuccessfulUploadingCsv()\    {\        $this-\u0026gt;json('POST', 'upload-new-users-csv', ['usersCsvFile' =\u0026gt; $this-\u0026gt;createUploadFile()]);\        $this-\u0026gt;assertResponseOk();\    }\\    protected function createUploadFile()\    {\        $vfs = vfsStream::setup(sys_get_temp_dir(), null, ['testFile' =\u0026gt; 'someString']);\\        return new UploadedFile(\            $vfs-\u0026gt;url().'/testFile',\            null,\            'text/csv',\            null,\            null,\            true\        );\    }\}
\

这里引入了很多内容,首先是vfsStream::setup,它会在内存中创建一个文件。样例中使用了“sys_get_temp_dir()”,这只是让它看起来“更真实一些”,这里可以使用任意的值,比如可以将其修改为字符串“root”,运行效果是完全一样的。这背后的理念是允许你创建任意的目录结构以适应实际的需求。\

这其实并不太重要,因为PHP会自动将上传的文件放到系统的临时目录中,所以只需使用“sys_get_temp_dir()”就可以,在这个场景中,它其实并没有什么关系。下一个参数用来设置文件权限,在本例中,我们没有特殊的要求,所以只需将其设置为null,这样允许你对文件进行任意操作。最后,是目录(本例中也就是“/tmp”)中的内容,它只是一个数组,由文件名(key)和值(现在是普通的字符串,不过后续需要改为CSV内容)所组成。\

最后,我们可以看到的是UploadedFile,它是对Symfony的UploadedFile的扩展,我们按顺序快速看一下它的参数(来源于Symfony的注释内容):\

第一个参数:文件的完整临时目录;

第二个参数:原始的文件名;

第三个参数:PHP所提供的文件类型,如果是null的话,默认为application/octet-stream;

第四个参数:文件大小;

第五个参数:上传出现错误的常量(PHP的UPLOAD_ERR_XXX常量之一),如果是null的话,默认为UPLOAD_ERR_OK;

第六个参数:是否启用测试模式。\

如果你运行PHPUnit的话,那么测试就能够通过了!现在,我们让文件看起来更真实一些,在createUploadFile函数中,将它的内容改为如下所示:

protected function createUploadFile()\{\    $vfs = vfsStream::setup(sys_get_temp_dir(), null, ['testFile.csv' =\u0026gt; '']);\\    $uploadFile = new UploadedFile(\        $vfs-\u0026gt;url().'/testFile.csv',\        null,\        'text/csv',\        null,\        null,\        true\    );\\    collect([\        ['username', 'first name', 'last name'],\        ['jondoe', 'Jon', 'Doe'],\        ['janedoe', 'Jane', 'Doe']\    ])-\u0026gt;each(function ($fields) use ($uploadFile) {\        $uploadFile-\u0026gt;openFile('a+')-\u0026gt;fputcsv($fields);\    });\\    return $uploadFile;\}
\

这里利用了Laravel的集合辅助工具,借助一些PHP的功能来填充文件。openFile()会得到底层的,然后直接使用它,将数组中的元素添加到文件中,就像CSV文件中的某行数据一样。运行PHPUnit,我们依然会得到绿色的测试通过提示。现在,我们要确保能够得到预期的结果,响应中的JSON要列出文件中的内容。要实现这项功能,将testSuccessfulUpload函数改成如下所示:

public function testSuccessfulUploadingCsv()\{\    $this-\u0026gt;json('POST', 'upload-new-users-csv', ['usersCsvFile' =\u0026gt; $this-\u0026gt;createUploadFile()])\        -\u0026gt;seeJson([\            \"username,\\\"first name\\\

转载地址:http://ojbnl.baihongyu.com/

你可能感兴趣的文章
CodeVS 1008 选数(DFS)
查看>>
SQL Server日常积累
查看>>
C++强制类型转换
查看>>
搭建FTP服务器 window7
查看>>
并发编程下的性能定律(翻译)
查看>>
cssText文本格式化
查看>>
新建koa2项目
查看>>
Phoenix 索引生命周期
查看>>
I,P,B帧和PTS,DTS的关系
查看>>
JavaOO练习:违规管理系统
查看>>
继续开始列车式的生活
查看>>
String的属性和方法
查看>>
hdu-1800
查看>>
读写锁-锁粒度
查看>>
C#_delegate - 用委托实现事件,Display和Log类都使用Clock对象
查看>>
java.net.BindException: 权限不够
查看>>
《c程序设计语言》读书笔记-字符型0-9转为数字0-9
查看>>
公务员队伍开始动荡了吗?
查看>>
项目中解决实际问题的代码片段-javascript方法,Vue方法(长期更新)
查看>>
sdut 1500 Message Flood(Trie树)
查看>>