如何在 PHP 中存根这个函数
How do I stub this function in PHP
我有以下class我想测试:
<?php
namespace Freya\Component\PageBuilder\FieldHandler;
use Freya\Component\PageBuilder\FieldHandler\IFieldHandler;
/**
* Used to get a set of non empty, false or null fields.
*
* The core purpose is to use this class to determine that A) Advanced Custom Fields is installed
* and B) that we get back a set of fields for a child page.
*
* The cavete here is that this class requires you to have child pages that then have Custom Fields that
* you want to display on each of those pages. getting other page information such as content, title, featured image
* and other meta boxes is left ot the end developer.
*
* @see Freya\Component\PageBuilder\FieldHandler\IFieldHandler
*/
class FieldHandler implements IFieldHandler {
/**
* {@inheritdoc}
*
* @return bool
*/
public function checkForAFC() {
return function_exists("register_field_group");
}
/**
* {@inheritdoc}
*
* @param $childPageID - the id of the child page who may or may not have custom fields.
* @return mixed - Null or Array
*/
public function getFields($childPageId) {
$fieldsForThisPage = get_fields($childPageId);
if (is_array($fieldsForThisPage)) {
foreach ($fieldsForThisPage as $key => $value) {
if ($value === "" || $value === false || $value === null) {
unset($fieldsForThisPage[$key]);
}
}
return $fieldsForThisPage;
}
return null;
}
}
我可以测试所有这些,但我想做的一件事是存根 get_fields()
函数,表示您将 return 这种类型的数组,然后将如何使用其余的函数使用它,在本例中循环遍历它。
我在 php 中不知道如何做的部分是存根正在调用的函数,然后说你将 return x.
那么我该如何存根 get_fields
?
您可以在全局命名空间中定义此类函数。看看下面的例子:
namespace {
function getFields($pageId) {
return array($pageId);
}
}
namespace MyNamespace {
class MyClass
{
public function foo(){
var_dump(getFields(5));
}
}
$obj = new MyClass();
$obj->foo();
}
这是输出:
array(1) {
[0]=>
int(5)
}
唯一的问题是这个函数将一直存在到脚本结束。要解决此问题,您可以将 tearDown 方法与 runkit 库一起使用:
http://php.net/manual/en/function.runkit-function-remove.php
允许您删除用户定义的函数。
不幸的是,这个库在 Windows 上不存在,因此您将无法删除该定义,并且可以考虑单独进行 运行 测试。
编辑:
你也可以考虑使用这个库(它也依赖于 runkit):
https://github.com/tcz/phpunit-mockfunction
你可以在这里使用 非限定函数名 get_fields()
的技巧。由于你没有使用 fully qualified 函数名 \get_fields()
PHP 将首先尝试在当前命名空间中查找函数,然后回退到全局函数名字.
合格和不合格的定义见:http://php.net/manual/en/language.namespaces.basics.php(类似于绝对文件名和相对文件名)
所以你要做的就是在 class 的命名空间中定义函数以及你的测试用例,如下所示:
namespace Freya\Component\PageBuilder\FieldHandler;
function get_fields()
{
return ['X'];
}
class FieldHandlerTest extends \PHPUnit_Test_Case
{
...
}
补充说明:
- 您可以对核心函数执行相同的操作,如下所述:http://www.schmengler-se.de/en/2011/03/php-mocking-built-in-functions-like-time-in-unit-tests/
- 此技巧仅适用于函数,不适用于 classes。全局命名空间中的 类 始终必须使用前导反斜杠引用。
我有以下class我想测试:
<?php
namespace Freya\Component\PageBuilder\FieldHandler;
use Freya\Component\PageBuilder\FieldHandler\IFieldHandler;
/**
* Used to get a set of non empty, false or null fields.
*
* The core purpose is to use this class to determine that A) Advanced Custom Fields is installed
* and B) that we get back a set of fields for a child page.
*
* The cavete here is that this class requires you to have child pages that then have Custom Fields that
* you want to display on each of those pages. getting other page information such as content, title, featured image
* and other meta boxes is left ot the end developer.
*
* @see Freya\Component\PageBuilder\FieldHandler\IFieldHandler
*/
class FieldHandler implements IFieldHandler {
/**
* {@inheritdoc}
*
* @return bool
*/
public function checkForAFC() {
return function_exists("register_field_group");
}
/**
* {@inheritdoc}
*
* @param $childPageID - the id of the child page who may or may not have custom fields.
* @return mixed - Null or Array
*/
public function getFields($childPageId) {
$fieldsForThisPage = get_fields($childPageId);
if (is_array($fieldsForThisPage)) {
foreach ($fieldsForThisPage as $key => $value) {
if ($value === "" || $value === false || $value === null) {
unset($fieldsForThisPage[$key]);
}
}
return $fieldsForThisPage;
}
return null;
}
}
我可以测试所有这些,但我想做的一件事是存根 get_fields()
函数,表示您将 return 这种类型的数组,然后将如何使用其余的函数使用它,在本例中循环遍历它。
我在 php 中不知道如何做的部分是存根正在调用的函数,然后说你将 return x.
那么我该如何存根 get_fields
?
您可以在全局命名空间中定义此类函数。看看下面的例子:
namespace {
function getFields($pageId) {
return array($pageId);
}
}
namespace MyNamespace {
class MyClass
{
public function foo(){
var_dump(getFields(5));
}
}
$obj = new MyClass();
$obj->foo();
}
这是输出:
array(1) {
[0]=>
int(5)
}
唯一的问题是这个函数将一直存在到脚本结束。要解决此问题,您可以将 tearDown 方法与 runkit 库一起使用:
http://php.net/manual/en/function.runkit-function-remove.php
允许您删除用户定义的函数。 不幸的是,这个库在 Windows 上不存在,因此您将无法删除该定义,并且可以考虑单独进行 运行 测试。
编辑: 你也可以考虑使用这个库(它也依赖于 runkit): https://github.com/tcz/phpunit-mockfunction
你可以在这里使用 非限定函数名 get_fields()
的技巧。由于你没有使用 fully qualified 函数名 \get_fields()
PHP 将首先尝试在当前命名空间中查找函数,然后回退到全局函数名字.
合格和不合格的定义见:http://php.net/manual/en/language.namespaces.basics.php(类似于绝对文件名和相对文件名)
所以你要做的就是在 class 的命名空间中定义函数以及你的测试用例,如下所示:
namespace Freya\Component\PageBuilder\FieldHandler;
function get_fields()
{
return ['X'];
}
class FieldHandlerTest extends \PHPUnit_Test_Case
{
...
}
补充说明:
- 您可以对核心函数执行相同的操作,如下所述:http://www.schmengler-se.de/en/2011/03/php-mocking-built-in-functions-like-time-in-unit-tests/
- 此技巧仅适用于函数,不适用于 classes。全局命名空间中的 类 始终必须使用前导反斜杠引用。