2

注意:这不是重复的问题。我见过一些类似的问题,但我问的是单元测试。

我正在尝试使用 CakePHP 2.3.6 编写测试用例,但使用 header() 函数的测试用例有问题。测试从浏览器运行没有问题,但从命令行,我收到以下错误。

Cannot modify header information - headers already sent by (output started at /usr/share/pear/PHPUnit/Util/Printer.php:172)

例如,错误发生在我的代码中的以下行。

header( 'Content-Type: application/json; charset=utf-8' );

对于 PHPUnit,可以使用 @runInSeparateProcess 来避免这种情况,但在 CakePHP 中,它会导致以下错误。

Notice: Constant TIME_START already defined in /app/lib/Cake/bootstrap.php on line 22
Notice: Constant CAKE already defined in /app/lib/Cake/bootstrap.php on line 48
Notice: Constant APPLIBS already defined in /app/lib/Cake/bootstrap.php on line 60
Notice: Constant SECOND already defined in /app/lib/Cake/basics.php on line 26
Notice: Constant MINUTE already defined in /app/lib/Cake/basics.php on line 27

等等。

我被困住了。有谁知道如何处理这个?提前非常感谢。

4

5 回答 5

3

检查您是否在标题行之前提供任何输出,通常是回显,也许您在标题行之前回显了一些 html

于 2013-09-27T04:15:31.840 回答
1

有关“已发送标头”的问题的所有其他答案都是正确的,但在您的情况下,这是某种专业。您无法摆脱这种情况,因为 PHPUnit 在运行到尝试发送标头的代码之前确实会发送输出。

但关键是:您不应该使用该header()功能。您应该为此使用该CakeResponse对象。我的快速谷歌搜索发现了这个(显然是 2.0,所以你应该找到更新的文档版本):http ://book.cakephp.org/2.0/en/controllers/request-response.html#cakeresponse

如果使用这个对象,整个测试过程可以避免header()在测试执行期间调用,因为你可以像这样注入一个模拟对象:http: //book.cakephp.org/2.0/en/controllers/request-response.html#cakeresponse-和测试

最后,如果您想顺利运行测试,以下基本规则适用于您的代码:

  • 不要调用任何依赖于某种情况的 PHP 函数(比如headers()依赖于没有echo第一个)或改变这种情况
  • 不要调用需要测试的 PHP 函数(例如“必须调用error_log发生”)

所有这些函数调用都应该包装到一个可以模拟的对象中。

于 2013-09-27T07:54:03.907 回答
1

您一定误解了单元测试实际上是什么。因此,请注意不要使用错误的工具来完成这项工作。

例如,在您的问题中,您写道:

例如,错误发生在我的代码中的以下行。

header( 'Content-Type: application/json; charset=utf-8' );

这行代码不是某行可以用 PHPUnit 测试的代码。不要试图在你的 Phpunit 测试中运行这样的代码,你总会在这里遇到问题。

所以你写得对,你被卡住了,我完全可以理解。但是,这也取决于观点。有些问题有一个非常明显的解决方案:不要这样做。而是使用正确的工具来测试它,例如使用通过 HTTP 协议访问您的应用程序的功能测试,以便他们可以测试 HTTP 响应标头。PHPUnit 不能——我不应该在这里说永远:至少不是你使用它的方式(我假设你想使用它)。

如果这不是一个选项,关于标头错误的规范问题概述了如何处理该错误的多种方法,建议的输出控制功能可能对您的测试有用:

该答案还应该告诉您有关从 PHP 发送标头的任何信息,以便您更好地了解正在测试的系统。

于 2013-09-27T13:30:44.720 回答
0

在发送标题之前不应发送任何输出!

必须在进行任何输出之前调用发送/修改 HTTP 标头的函数。否则调用失败。查找输出到屏幕的任何错误或任何打印或回显语句。

请参阅此处接受的答案。

于 2013-09-27T04:07:59.620 回答
0

The problem is that, your approach is not right! PHPUnit is supposed to do UNIT tests but what you are trying to do is more behavioural tests which can be done using Behat/Mink like tests.

If you are going to use Unit tests then you have to decouple units of your system and do the testing Unit by Unit, in case of redirection you can use mockups to catch redirection functionality and do a proper checking for that.

于 2013-12-17T06:01:13.767 回答