使用 PHPUnit 测试 PHP 标头

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9745080/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 07:33:31  来源:igfitidea点击:

Test PHP headers with PHPUnit

phpunit-testingphpunitoutput-buffering

提问by titel

I'm trying to use PHPunit to test a class that outputs some custom headers.

我正在尝试使用 PHPunit 来测试输出一些自定义标头的类。

The problem is that on my machine this:

问题是在我的机器上:

<?php

class HeadersTest extends PHPUnit_Framework_TestCase {

    public function testHeaders()
    {
        ob_start();

        header('Location: foo');
        $headers_list = headers_list();
        header_remove();

        ob_clean();

        $this->assertContains('Location: foo', $headers_list);
    }
}

or even this:

甚至这个:

<?php

class HeadersTest extends PHPUnit_Framework_TestCase {

    public function testHeaders()
    {
        ob_start();

        header('Location: foo');
        header_remove();

        ob_clean();
    }
}

return this error:

返回此错误:

name@host [~/test]# phpunit --verbose HeadersTest.php 
PHPUnit 3.6.10 by Sebastian Bergmann.

E

Time: 0 seconds, Memory: 2.25Mb

There was 1 error:

1) HeadersTest::testHeaders
Cannot modify header information - headers already sent by (output started at /usr/local/lib/php/PHPUnit/Util/Printer.php:173)

/test/HeadersTest.php:9

FAILURES!
Tests: 1, Assertions: 0, Errors: 1.

This looks as if there is something else outputting to the terminal before the test runs even though there is no other file included and there is no other character before the beginning of the PHP tag. Could it be something inside PHPunit that is causing this?

这看起来好像在测试运行之前有其他东西输出到终端,即使没有包含其他文件并且在 PHP 标记的开头之前没有其他字符。会不会是 PHPunit 内部的某些东西导致了这种情况?

What could the issue be?

可能是什么问题?

回答by SamHennessy

The issue is that PHPUnit will print a header to the screen and at that point you can't add more headers.

问题是 PHPUnit 将在屏幕上打印一个标题,此时您无法添加更多标题。

The work around is to run the test in an isolated process. Here is an example

解决方法是在隔离的进程中运行测试。这是一个例子

<?php

class FooTest extends PHPUnit_Framework_TestCase
{
    /**
     * @runInSeparateProcess
     */
    public function testBar()
    {
        header('Location : http://foo.com');
    }
}

This will result in:

这将导致:

$ phpunit FooTest.php
PHPUnit 3.6.10 by Sebastian Bergmann.

.

Time: 1 second, Memory: 9.00Mb

OK (1 test, 0 assertions)

The key is the @runInSeparateProcess annotation.

关键是@runInSeparateProcess 注释。

If you are using PHPUnit ~4.1 or something and get the error:

如果您使用 PHPUnit ~4.1 或其他东西并收到错误消息:

PHP Fatal error:  Uncaught Error: Class 'PHPUnit_Util_Configuration' not found in -:378
Stack trace:
#0 {main}
  thrown in - on line 378

Fatal error: Uncaught Error: Class 'PHPUnit_Util_Configuration' not found in - on line 378

Error: Class 'PHPUnit_Util_Configuration' not found in - on line 378

Call Stack:
    0.0013     582512   1. {main}() -:0

Try add this to your bootstrap file to fix it:

尝试将其添加到您的引导程序文件中以修复它:

<?php
if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
    define('PHPUNIT_COMPOSER_INSTALL', __DIR__ . '/path/to/composer/vendors/dir/autoload.php');
}

回答by Jon Cairns

Although running the test in a separate process does fix the problem, there's a noticeable overhead when running a large suite of tests.

尽管在单独的进程中运行测试确实可以解决问题,但在运行大量测试时会产生明显的开销。

My fix was to direct phpunit's output to stderr, like so:

我的解决方法是将 phpunit 的输出定向到 stderr,如下所示:

phpunit --stderr <options>

That should fix the problem, and it also means that you don't have to create a wrapper function and replace all occurrences in your code.

这应该可以解决问题,这也意味着您不必创建包装函数并替换代码中出现的所有内容。

回答by Melle

As an aside: For me headers_list()kept returning 0 elements. I noticed @titel's comment on the question and figured it deserves special mention here:

顺便说一句:对我来说,headers_list()一直返回 0 个元素。我注意到@titel对这个问题的评论,并认为这里值得特别提及:

Just wanted to cover this if there are some other people interested in this as well. headers_list()doesn't work while running PHPunit (which uses PHP CLI) but xdebug_get_headers()works instead.

如果还有其他人对此感兴趣,我只是想介绍一下。headers_list()运行 PHPunit(使用 PHP CLI)时不起作用,但xdebug_get_headers()可以运行。

HTH

HTH

回答by Sergio Abreu

I had a more radical solution, in order to use $_SESSIONinside my tested/includedfiles. I edited one of the PHPUnitfiles at ../PHPUnit/Utils/Printer.phpto have a "session_start();"before the command "print $buffer".

我有一个更激进的解决方案,以便$_SESSION在我测试/包含的文件中使用。我在../PHPUnit/Utils/Printer.php编辑了一个PHPUnit文件,在命令“print $buffer”之前有一个。"session_start();"

It worked for me like a charm. But I think "joonty" user's solution is the best of all up to now.

它对我来说就像一种魅力。但我认为“joonty”用户的解决方案是迄今为止最好的。

回答by PepeNietnagel

As already mentioned in a comment, I think it's a better solution to define processIsolation in the XML config file like

正如评论中已经提到的,我认为在 XML 配置文件中定义 processIsolation 是一个更好的解决方案,例如

     <?xml version="1.0" encoding="UTF-8"?>
     <phpunit
        processIsolation            = "true"
        // ... 
     >
     </phpunit>

Like this, you don't have to pass the --stderr option, which might irritate your co-workers.

像这样,您不必传递 --stderr 选项,这可能会激怒您的同事。

回答by NSukonny

Use --stderr parameter for getting headers from PHPUnit after your tests.

使用 --stderr 参数在测试后从 PHPUnit 获取标头。

phpunit --stderr

回答by AlexB

An alternative solution to @runInSeparateProcess is to specify the --process-isolation option when running PHPUnit:

@runInSeparateProcess 的另一种解决方案是在运行 PHPUnit 时指定 --process-isolation 选项:

name@host [~/test]# phpunit --process-isolation HeadersTest.php

That is analogous to set the processIsolation="true" option in phpunit.xml.

这类似于在 phpunit.xml 中设置 processIsolation="true" 选项。

This solution has similar advantages/disadvantages to specifying the --stderr option, which however did not work in my case. Basically no code changes are necessary, even though there may be a performance hit due to running each test in a separate PHP process.

此解决方案与指定 --stderr 选项具有类似的优点/缺点,但在我的情况下不起作用。基本上不需要更改代码,即使由于在单独的 PHP 进程中运行每个测试可能会影响性能。