CakePHP / phpunit:如何模拟文件上传
CakePHP / phpunit : how to mock a file upload
我正在尝试为一个端点编写测试,该端点需要一个带有附加 CSV 文件的 post 请求。我知道像这样模拟 post 请求:
$this->post('/foo/bar');
但我不知道如何添加文件数据。我尝试手动设置 $_FILES
数组,但没有成功...
$_FILES = [
'csvfile' => [
'tmp_name' => '/home/path/to/tests/Fixture/csv/test.csv',
'name' => 'test.csv',
'type' => 'text/csv',
'size' => 335057,
'error' => 0,
],
];
$this->post('/foo/bar');
正确的做法是什么?
据我所知,CakePHP 神奇地结合了 $_FILES
、$_POST
等内容,因此我们可以从 $this->request->data[...]
访问每个内容。您可以使用可选的第二个参数将信息传递给该数据数组:
$data = [
'csvfile' => [
'tmp_name' => '/home/path/to/tests/Fixture/csv/test.csv',
'name' => 'test.csv',
'type' => 'text/csv',
'size' => 45,
'error' => 0,
],
];
$this->post('/foo/bar', $data);
模拟核心 PHP 函数有点棘手。
我猜你的帖子模型中有类似的东西。
public function processFile($file)
{
if (is_uploaded_file($file)) {
//process the file
return true;
}
return false;
}
而你有这样一个相应的测试。
public function testProcessFile()
{
$actual = $this->Posts->processFile('noFile');
$this->assertTrue($actual);
}
由于您在测试过程中没有上传任何东西,所以测试总是会失败。
您应该在 PostsTableTest.php 的开头添加第二个命名空间,即使在单个文件中包含更多命名空间也是一种不好的做法。
<?php
namespace {
// This allows us to configure the behavior of the "global mock"
// by changing its value you switch between the core PHP function and
// your implementation
$mockIsUploadedFile = false;
}
比起你的原始命名空间声明,你应该使用大括号格式。
namespace App\Model\Table {
并且可以添加PHP要覆盖的核心方法
function is_uploaded_file()
{
global $mockIsUploadedFile;
if ($mockIsUploadedFile === true) {
return true;
} else {
return call_user_func_array('\is_uploaded_file',func_get_args());
}
}
//other model methods
} //this closes the second namespace declaration
关于 CakePHP 单元测试的更多信息:http://www.apress.com/9781484212134
我正在尝试为一个端点编写测试,该端点需要一个带有附加 CSV 文件的 post 请求。我知道像这样模拟 post 请求:
$this->post('/foo/bar');
但我不知道如何添加文件数据。我尝试手动设置 $_FILES
数组,但没有成功...
$_FILES = [
'csvfile' => [
'tmp_name' => '/home/path/to/tests/Fixture/csv/test.csv',
'name' => 'test.csv',
'type' => 'text/csv',
'size' => 335057,
'error' => 0,
],
];
$this->post('/foo/bar');
正确的做法是什么?
据我所知,CakePHP 神奇地结合了 $_FILES
、$_POST
等内容,因此我们可以从 $this->request->data[...]
访问每个内容。您可以使用可选的第二个参数将信息传递给该数据数组:
$data = [
'csvfile' => [
'tmp_name' => '/home/path/to/tests/Fixture/csv/test.csv',
'name' => 'test.csv',
'type' => 'text/csv',
'size' => 45,
'error' => 0,
],
];
$this->post('/foo/bar', $data);
模拟核心 PHP 函数有点棘手。
我猜你的帖子模型中有类似的东西。
public function processFile($file)
{
if (is_uploaded_file($file)) {
//process the file
return true;
}
return false;
}
而你有这样一个相应的测试。
public function testProcessFile()
{
$actual = $this->Posts->processFile('noFile');
$this->assertTrue($actual);
}
由于您在测试过程中没有上传任何东西,所以测试总是会失败。
您应该在 PostsTableTest.php 的开头添加第二个命名空间,即使在单个文件中包含更多命名空间也是一种不好的做法。
<?php
namespace {
// This allows us to configure the behavior of the "global mock"
// by changing its value you switch between the core PHP function and
// your implementation
$mockIsUploadedFile = false;
}
比起你的原始命名空间声明,你应该使用大括号格式。
namespace App\Model\Table {
并且可以添加PHP要覆盖的核心方法
function is_uploaded_file()
{
global $mockIsUploadedFile;
if ($mockIsUploadedFile === true) {
return true;
} else {
return call_user_func_array('\is_uploaded_file',func_get_args());
}
}
//other model methods
} //this closes the second namespace declaration
关于 CakePHP 单元测试的更多信息:http://www.apress.com/9781484212134