如何模拟PHPUnit的HTTP请求?

时间:2014-02-04 作者:Daithí

我正在编写一个插件,向Facebook graph API发出请求。由于我不希望我的单元测试实际发出这些请求,我该如何克服这一问题?我的方法同时调用wp_remote_getwp_remote_post. 在那里搜索似乎是一种模拟函数的方法runkit, here

我希望避免让贡献者需要太多依赖项,因此希望避免使用上述方法。还有其他选择吗?我的类扩展了WP_UnitTestCase 所以我希望wp单元测试中有一些我可以使用的东西?

5 个回复
最合适的回答,由SO网友:Rarst 整理而成

如果你看看WP_HTTP->request() (所有相关函数都将其包装)它提供了一个过滤器挂钩,用于覆盖发出的请求,以支持将任意数据作为响应返回:

// Allow plugins to short-circuit the request
$pre = apply_filters( \'pre_http_request\', false, $r, $url );
if ( false !== $pre )
    return $pre;

SO网友:kaiser

在一(两)个字中:模拟数据。PHPUnit获得getMock() 完全适用于此。正如其他答案已经完美召唤的那样…

从何处获取有效的模拟数据(Otto)-确保偶尔获取新数据、从何处截取数据(Rarst)以及使用什么工具(TomJNowell);只剩下(可能)一个问题,您的本地SSL证书验证可能会失败。WP附带过滤器:

add_filter( \'https_local_ssl_verify\', \'__return_false\' );
有关WP HTTP API的更多信息,您可能需要深入了解this answer, this answer, this answer by @Wyckthis answer by @toscho.

SO网友:Otto

获取从有效或无效请求获得的结果,将其序列化为字符串,然后将取消序列化字符串的代码添加回变量中,而不是执行请求。

SO网友:Tom J Nowell

为了进一步隔离代码,我将包装wp_remote_get etc在具有两个实现的接口中调用。一个实现调用wp_remote_get, 另一个返回测试数据。

在这种情况下,使用runkit之类的工具可以避免您所面临的实际问题,即您的代码和API的耦合过于紧密,封装和抽象级别将是有益的。

SO网友:J.D.

有几次我不得不模仿WordPress的HTTP请求功能,因此我决定构建一个工具来实现这一点:WP HTTP TestCase

基本上,它提供了一种简单的方法来完成其他答案所概述的各种事情。自述文件:

用于测试使用WordPress的代码的WP HTTP测试用例WP_Http

如果您使用wp_remote_request() 或其他包装WP_Http 方法,这使得测试变得很困难,尤其是在无法从测试环境访问远程服务器的情况下。这个测试用例通过允许您将请求路由到不同的主机地址、使用缓存的响应集或通过提供人工响应来模拟远程响应来解决这个问题。

安装可以使用composer安装此软件包:

composer require --dev jdgrimes/wp-http-testcase:~1.1

用法要在代码中使用它,首先需要包括wp-http-testcase.php PHPUnit引导文件中的文件。如果要使用主机路由和响应缓存功能,则需要调用WP_HTTP_TestCase::init() 在引导文件中。

然后,在你的测试中WP_Http, 您需要扩展WP_HTTP_TestCase 而不是WP_UnitTestCase 就像你平时一样。

使用响应缓存模拟响应是最好的测试方法,如果可能,可以设置模拟主机来处理请求。在某些情况下,您可能希望或需要实际将请求发送到真正的服务器,也可以这样做。您要做哪一项取决于请求的性质,以及它们对接收方主机产生的副作用。

例如,设置测试主机,如果您正在测试一个插件,该插件向另一个插件或其他软件提供的API发出请求,那么您可能不希望或不需要在实时站点上测试该插件。相反,您可以设置测试站点,或者使用作为开发环境一部分的本地服务器。您可以在那里安装处理请求的软件。完成此操作后,您可以对该测试站点运行测试,如下所示:

WP_HTTP_TC_HOST=localhost phpunit

只需更换localhost 使用本地服务器的主机名。请注意WP_HTTP_TC_* 标志可以定义为PHP常量,也可以如上所述定义为bash环境变量。后者将优先。

当然,启用缓存要比大多数其他单元测试慢得多,因为请求肯定会花费一些时间。这就是缓存的用武之地。启用缓存后,每个请求的响应将在第一次运行时进行缓存,并在将来使用缓存的版本。这意味着您的测试可以保持闪电般的速度。

要启用缓存,只需将其添加到引导程序中:

define( \'WP_HTTP_TC_USE_CACHING\', true );

您可能还希望通过以下方式指定保存缓存的目录:WP_HTTP_TC_CACHE_DIR. 您可以使用多个缓存组,并使用WP_HTTP_TC_CACHE_GROUP.

但是,使用实时主机还有第二种情况,您无法设置测试服务器。例如,如果插件向GitHub提供的API发出请求,就会出现这种情况。根据具体情况,向“实时”收件人发出请求可能是可行的。主要问题是,这些请求将使测试需要很长时间才能完成。还有一种可能性是,API并不总是可以从您的测试环境中访问,或者您的测试最终会对API造成太大的冲击,您将被阻止。这就是缓存可以帮助您的地方。您只需要偶尔对“实时”API运行一次测试,其余时间可以使用缓存的响应进行测试。

当然,有时不可能创建测试服务器,也不可能在实时服务器上运行。在这种情况下,您可能希望将人工响应硬编码到测试中。以下是如何做到这一点:

在调用将调用HTTP请求的代码之前,需要将函数设置为模拟响应,如下所示:

$this->http_responder = array( $this, \'mock_server_response\' );

HTTP响应程序函数将被传递两个参数,请求参数和请求的目标URL。

protected function mock_server_response( $request, $url ) {
   return array( \'body\' => \'Test response.\' ); 
}
有关$request 和响应参数,请参见WP_Http::request()

结束

相关推荐

How deactivate the http-api

为它提供一个tipp或解决方案来停用WP\\U Http\\U Streams类中的方法request()?我也在脱机服务器上使用WordPress,并让wp\\U debug true用于开发和测试。但是我从函数中得到了很多关于使用http类的警告;例如,在仪表板中读取提要的函数。目前我已经停用了更新主题、插件、核心和cron的所有挂钩;请参阅我的小插件:https://github.com/bueltge/WP-Offline谢谢你的回复