How to test for expected headers?

落爺英雄遲暮 提交于 2019-12-17 18:57:30

问题


I have a unit test that fails because headers are already sent. However, the header in this scenario is expected.

How do I tell PHPUnit to expect a 500 header?

I've read this question but it didn't help.

The method is wrapped inside an output buffer.

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

回答1:


If you have xdebug installed you can use xdebug_get_headers() to get the headers. Then you can test them as needed.

$headers=xdebug_get_headers();

gets you an array which looks like...

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

So you'll need to parse each header line to separate the header name from the value




回答2:


If you can't use xdebug_get_headers on your system, another approach is to mock the header function.

I'm using the following now, which works great. Lets say you have this code...

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

I replace header with a header function which is testable like this...

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

The Testable class is implemented as follows. Note that functions just need to be prepended with Testable::. Otherwise they work just the same as the usual functions.

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();
      }
   }
}

Now all you need to do is define UNIT_TESTING in your tests, but not in production. Then when you come to test your headers, just call Testable::headers_list().

You should of course add methods for setcookie, headers_sent and any other functions which issue HTTP headers.




回答3:


Another possible approach is to override the header php function for the namespace you are testing. 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 = [];
    }
}

Then in your test class

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
        );
    }
}

You can keep your code clean and you don't need xdebug



来源:https://stackoverflow.com/questions/9127252/how-to-test-for-expected-headers

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!