【问题标题】:How to test for expected headers?如何测试预期的标题?
【发布时间】:2012-02-25 23:43:13
【问题描述】:

我有一个单元测试失败,因为标头已经发送。但是,此方案中的标头是预期的。

我如何告诉 PHPUnit 期待 500 标头?

我读过this question,但没有帮助。

该方法被包装在一个输出缓冲区中。

ob_start();
$foo->methodWhichSendsHeader();
ob_clean();

【问题讨论】:

标签: phpunit


【解决方案1】:

如果您安装了 xdebug,您可以使用 xdebug_get_headers() 来获取标头。然后您可以根据需要对其进行测试。

$headers=xdebug_get_headers();

为您提供一个看起来像...的数组

array(
    0 => "Content-type: text/html",
    1 => ...
)

因此您需要解析每个标题行以将标题名称与值分开

【讨论】:

  • 这适用于header('Content-Type: text/html'); 格式的调用,但它似乎不适用于header('HTTP/1.1 500 Internal Server Error'); 格式的调用是否有获取这些标头/状态码的方法?
  • 虽然您无法从header('HTTP/1.1 500 Internal Server Error'); 获取实际的标头内容,但您可以使用内置的http_response_code() 来检索将返回的HTTP 状态码到浏览器。
【解决方案2】:

如果您不能在系统上使用 xdebug_get_headers,另一种方法是模拟标头函数。

我现在正在使用以下,效果很好。假设您有此代码...

<?php
header('Content-type: text/plain; charset=UTF-8');
...

我将header 替换为可以像这样测试的标头函数...

<?php
Testable::header('Content-type: text/plain; charset=UTF-8');
...

Testable 类实现如下。请注意,函数只需要在前面加上Testable::。否则,它们的工作方式与通常的功能相同。

class Testable {
   private static $headers=array();

   static function header($header) {
      if (defined('UNIT_TESTING')) {
         self::$headers[]=$header;
      } else {
         header($header);
      }
   }

   public static function reset() {
      self::$headers=array();
   }

   public static function headers_list() {
      if (defined('UNIT_TESTING')) {
          return self::$headers;
      } else {
          return headers_list();
      }
   }
}

现在您需要做的就是在您的测试中定义UNIT_TESTING,而不是在生产中。然后,当您来测试您的标头时,只需致电Testable::headers_list()。

您当然应该为 setcookie、headers_sent 和任何其他发出 HTTP 标头的函数添加方法。

【讨论】:

  • @JimmyKane - 据我所知,只不过是任何模拟。您可以在生产代码中保留对 Testable::header 的调用,只要在生产中未定义 UNIT_TESTING。我在这里缺少什么吗?
  • 我的意思是你必须在你的类中添加一个静态函数,从而修改Testable类。我不想在每个发送标题的摘要中编辑和添加静态 this 以便可测试。但这只是一种偏好。除此之外,你的回答很好。祝你有美好的一天。
  • 啊,Testable 类不是被测类。它被称为“这是一个可测试的标头函数”,而不是标准的。我选择的类名不是很清楚,我将对其进行编辑以使其更清晰。
  • 希望现在更清楚一点。感谢您的 cmets,绝对是为了更好的答案!
【解决方案3】:

另一种可能的方法是覆盖您正在测试的命名空间的header php 函数。 https://www.codepunker.com/blog/overwrite-built-in-php-functions-using-namespaces

namespace My\Application\Namespace;
use My\Test\Application\Namespace;    

//this overrides the header function for that namespace
//it works only if the function is called without the backslash
function header($string){
    HeaderCollector::$headers[] = $string;
}

namespace My\Test\Application\Namespace

/**
 * Class HeaderCollector
 * Using this in combination with function header override
 * for the namespace My\Application\Namespace
 * we can make assertions on headers sent
 */
class HeaderCollector {

    public static $headers = [];

    //call this in your test class setUp so headers array is clean before each test
    public static function clean() {
        self::$headers = [];
    }
}

然后在你的测试类中

namespace My\Test\Application\Namespace
use PHPUnit\Framework\TestCase;


class MyTest extends TestCase {

    protected function setUp() {
        parent::setUp();
        //clean for each test
        HeaderCollector::clean();
    }

    public function testHeaders() {
        //call the code that send headers
        ...

        self::assertEquals(
            ["Content-Type: text/html; charset=UTF-8", "Another-Header..."],
            HeaderCollector::$headers
        );
    }
}

你可以保持你的代码干净,你不需要 xdebug

【讨论】:

    猜你喜欢
    • 2015-06-12
    • 2017-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 2012-09-13
    • 1970-01-01
    相关资源
    最近更新 更多